Python – Handles Watchdog’s OSError

Handles Watchdog’s OSError… here is a solution to the problem.

Handles Watchdog’s OSError

I’ve been using the tkinter combo watchdog module for some upload requests. Most of the time it works fine, but sometimes our network drive becomes unstable and disconnects for a while. But I can’t find the right place to catch this error.

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import tkinter as tk

root = tk. Tk()
path = [r"Network path 1",r"Network path 2"]

class MyGui:
    def __init__(self,master):
        self.master = master
        self.but = tk. Button(master,text="Click to start observer",command=self.start_observer)
        self.but.pack()

def start_observer(self):
        for i in path:
            observer.schedule(event_handler, path=i, recursive=False)
        observer.start()
        self.but.config(state="disabled",text="observer started")
        print ("Observer started")

class MyHandler(FileSystemEventHandler):
    def on_created(self, event):
        current_file = event.src_path
        print (current_file)

event_handler = MyHandler()
observer = Observer()

gui = MyGui(root)
root.mainloop()

This is what I got after letting it run for a few days :

Exception in thread Thread-4:
Traceback (most recent call last):
  File "C:\Users\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917, in _bootstrap_inner
    self.run()
  File "C:\Users\AppData\Local\Programs\Python\Python37\lib\site-packages\watchdog\observers\api.py", line 146, in run
    self.queue_events(self.timeout)
  File "C:\Users\AppData\Local\Programs\Python\Python37\lib\site-packages\watchdog\observers\read_directory_changes.py", line 75, in queue_events
    winapi_events = read_events(self._handle, self.watch.is_recursive)
  File "C:\Users\AppData\Local\Programs\Python\Python37\lib\site-packages\watchdog\observers\winapi.py", line 346, in read_events
    buf, nbytes = read_directory_changes(handle, recursive)
  File "C:\Users\AppData\Local\Programs\Python\Python37\lib\site-packages\watchdog\observers\winapi.py", line 306, in read_directory_changes
    raise e
  File "C:\Users\AppData\Local\Programs\Python\Python37\lib\site-packages\watchdog\observers\winapi.py", line 302, in read_directory_changes
    ctypes.byref(nbytes), None, None)
  File "C:\Users\AppData\Local\Programs\Python\Python37\lib\site-packages\watchdog\observers\winapi.py", line 107, in _errcheck_bool
    raise ctypes. WinError()
OSError: [WinError 64] The specified network name is no longer available.

Can anyone suggest how to properly handle this exception?

Solution

Here’s how I solved this problem :

    from watchdog import observers
    from watchdog.observers.api import DEFAULT_OBSERVER_TIMEOUT, BaseObserver

class MyEmitter(observers.read_directory_changes. WindowsApiEmitter):
        def queue_events(self, timeout):
            try:
                super().queue_events(timeout)
            except OSError as e:
                print(e)
                connected = False
                while not connected:
                    try:
                        self.on_thread_start()  # need to re-set the directory handle.
                        connected = True
                        print('reconnected')
                    except OSError:
                        print('attempting to reconnect...')
                        time.sleep(10)

observer = BaseObserver(emitter_class=MyEmitter, timeout=DEFAULT_OBSERVER_TIMEOUT)
    ...

Subclassing WindowsApiEmitter to catch exceptions in queue_events. In order to continue after reconnecting, watchdog needs to reset the directory handle, which we can do using self.on_thread_start().

Then using MyEmitter with BaseObserver, we can now handle lost and reconnected connections to shared drives.

Related Problems and Solutions