guagay_wk
guagay_wk

Reputation: 28050

Make this directory sync script detect change and run in the background

I have this simple python script which will synchronize the contents of sourcedir folder to targetdir folder.

Here is the code;

from dirsync import sync

sourcedir = "C:/sourcedir"
targetdir ="C:/targetdir"
sync(sourcedir, targetdir, "sync")

It is cumbersome to manually run this script whenever changes are made. I would like to have this script running in the background so that whenever there is any change in sourcedir folder, targetdir folder will be synchronized automatically.

I am using python v3.5

Upvotes: 6

Views: 6187

Answers (7)

Abdulkader Khateeb
Abdulkader Khateeb

Reputation: 107

You may use watchdog, a recently updated python utility to monitor file system events.

This code from documentation:

import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    path = sys.argv[1] if len(sys.argv) > 1 else '.'
    event_handler = LoggingEventHandler()
    observer = Observer()
    observer.schedule(event_handler, path, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    finally:
        observer.stop()
        observer.join()

Upvotes: 1

Taufiq Rahman
Taufiq Rahman

Reputation: 5704

For Windows, you have watcher, a Python port of the .NET FileSystemWatcher API.

And for Linux, inotifyx which is a simple Python binding to the Linux inotify file system event monitoring API.

Upvotes: 3

charli
charli

Reputation: 1778

If you're running your script on linux, you can use inotify. (GitHub).

It uses a kernel feature that notifies an event when something happens in a watched directory, as file modification, access, creation, etc. This has very little overhead, as it's using epoll system call to watch for changes.

import inotify.adapters

i = inotify.adapters.Inotify()
i.add_watch(b'/tmp')
try:
    for event in i.event_gen():
        if event is not None:
            (header, type_names, watch_path, filename) = event
            if 'IN_MODIFY' in type_names:
                # Do something
                sync(sourcedir, targetdir, "sync")
finally:
    i.remove_watch(b'/tmp')

Also, it's recommended to use multiprocessing to execute the sync part, unless the script will not watch for changes during the sync process. Depending on your sync implementation, this could lead to process synchronization problems, a huge topic to discuss here.

My advice, try the easy approach, running everything on the same process and test if it suits your needs.

Upvotes: 3

Kenan Kocaerkek
Kenan Kocaerkek

Reputation: 319

You can use FindFirstChangeNotification function of win32 api.

http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html

Upvotes: 2

Wayne Werner
Wayne Werner

Reputation: 51837

There's an app a library for that:

import sys
import time
import logging
from watchdog.observers import Observer


def event_handler(*args, **kwargs):
    print(args, kwargs)


if __name__ == "__main__":
    path = '/tmp/fun'
    observer = Observer()
    observer.schedule(event_handler, path, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

Upvotes: 5

Christian Geier
Christian Geier

Reputation: 2149

You could check for the modification time (e.g., with os.path.getmtime(sourcepath)) of the source dir and only synchronize if it changed.

import os
import time
from dirsync import sync

sourcedir = "C:/sourcedir"
targetdir ="C:/targetdir"

mtime, oldmtime = None, None

while True:
    mtime = os.path.getmtime(sourcedir)
    if mtime != oldmtime:
        sync(sourcedir, targetdir, "sync")
        oldmtime = mtime
    time.sleep(60)

Upvotes: 2

Ove Halseth
Ove Halseth

Reputation: 461

I think this two links should get you started:

Python WMI example

VBScript Filesystemwatcher example

The basic idea is to query the WMI and get notified to changes in a folder/file.

Upvotes: 2

Related Questions