Home > Enterprise >  How to create a copy of a file after observing the event using File Listener (watchdog) in Python?
How to create a copy of a file after observing the event using File Listener (watchdog) in Python?

Time:06-25

I have below code which is listening to any excel file in one my directory. Below code is working file. However, I would like to modify the code such that as soon as new file arrives in the path it creates a copy of the same file in another folder. Let's say folder name is "today". I am not sure how to create a copy of same file as soon as new event is observed ? The copied file should be of same extension. In this case it will be excel

I am new to OOP so any help is much appreciated!

from watchdog.observers import Observer  
from watchdog.events import PatternMatchingEventHandler
import time

class FileWatcher(PatternMatchingEventHandler):
    patterns = ["*.xlsx"] 

    def process(self, event):
        
       # event.src_path will be the full file path
       # event.event_type will be 'created', 'moved', etc.
       print('{} observed on {}'.format(event.event_type, event.src_path))

    def on_created(self, event):
        self.process(event)

if __name__ == '__main__':
    obs = Observer() 
    obs.schedule(FileWatcher(), path='path/')
    print("Monitoring started....")
    obs.start() # Start watching

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        ob.stop()

    obs.join()

CodePudding user response:

Not sure why this is a problem. But if I understand correctly, you only need to

import os, shutil

and in

def on_created(self, event):
    self.process(event)
    destination = os.path.join(os.getcwd(), 'today', event.src_path.split('\\')[-1])
    shutil.copyfile(event.src_path, destination)

if you want "today" to be a subfolder of your curernt script's working directory. If not set the path to something else

UPDATE

Problem 1: Pausing the watchdog, wasn't so hard. It queues consequtive triggers (Events) and executes them

Problem 2: The trigger is executed, when the file is created. That doesn't mean the OS is finished writing it, hence the I/O Exception when trying to access / copy it. You have to wait for the file to be completely written. The EventHandler has no means of telling, so you have to implement a workaround. I have added the code below, that should do the trick.

from watchdog.observers import Observer  
from watchdog.events import PatternMatchingEventHandler
import time, os, shutil

class FileWatcher(PatternMatchingEventHandler):
    patterns = ["*.xlsx"] 

   def process(self, event):
        
        # event.src_path will be the full file path
        # event.event_type will be 'created', 'moved', etc.
        print('{} observed on {}'.format(event.event_type, event.src_path))

    def on_created(self, event):
        self._is_paused = True
        
        # WAITING FOR FILE TRANSFER
        file = None
        while file is None:
            try:
                file = open(event.src_path)
            except OSError:
                file = None                    
                time.sleep(1) # WAITING FOR FILE TRANSFER
                continue
        
        self.process(event)
        destination = os.path.join(os.getcwd(), 'today', event.src_path.split('\\')[-1])
        shutil.copyfile(event.src_path, destination)        
        self._is_paused = False

if __name__ == '__main__':
    
    obs = Observer() 
    obs.schedule(FileWatcher(), path='.\\')
    print("Monitoring started....")
    obs.start() # Start watching

    try:
        while obs.isAlive():
            obs.join()
    finally:
        obs.stop()
        obs.join()
  • Related