正确处理错误使用看门狗

2024-06-10 23:14:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图理解如何在Python中使用正确的错误处理。 我让看门狗在一张联网的光盘里查我的文件夹。有时光盘很快就会断开连接,然后再次连接,并弹出一个错误。”线程2出现异常:“

我有一个错误的处理,但我不确定我做得对。在

我要不要再试一次观察员计划台阶?在

Python 3.6、Windows 10

if __name__ == '__main__':
    path = "P:\\03_auto\\Indata"
    observer = Observer()
    observer.schedule(MyHandler(), path, recursive=True)
    observer.start()

    try:
        while True:
            time.sleep(1)
    except keyboardInterrupt:
        observer.stop()

    observer.join()

Tags: pathname文件夹trueifmainwindows错误
3条回答

好吧,我在评论中提到的sys.excepthook方法目前不可行。有一个已有十多年历史的bug使得从threading.Thread派生的线程忽略{}。在该错误的消息线程中列出了一些解决方法,但是我很高兴使用一个变通方法来发布一个答案,特别是这个bug最终似乎得到了python3.8的修复。

另一种选择是从看门狗的观察者派生一个定制的观察者。 我能想到的最基本的方法是父级run()方法的包装:

class CustomObserver(Observer):

    def run(self):
        while self.should_keep_running():
            try:
                # Tweak the super call if you require compatibility with Python 2
                super().run()
            except OSError: 
            # You did not mention the excpetion class in your post.
            # Be specific about what you want to handle here
                # give the file system some time to recover
                time.sleep(.5)

通过快速浏览源代码,所有观察者似乎都从^{}继承了他们的run,因此您甚至可以省略包装器并直接重新实现该方法

^{pr2}$

但是,我的盒子上没有安装这个软件包,所以这些东西还没有经过测试;你可能得在这上面瞎搞一番。 哦,并且确保用实际引发的异常类替换OSError*。)

编辑:
*根据@HenryYik下面的评论,断开网络驱动器的连接在Windows系统上似乎引发了一个OSError(winerror64:ERROR_NETNAME_DELETED)。我发现在这种情况下,UNIX风格的操作系统很可能会引发相同类型的异常,因此我更新了代码片段,现在使用OSError,而不是原来使用的FileNotFoundError。在

我也把这个贴在了一个相关的帖子here

我就是这样解决这个问题的:

    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)
    ...

子类化WindowsApiEmitter以捕获queue_events中的异常。为了在重新连接后继续,watchdog需要重新设置目录句柄,我们可以使用self.on_thread_start()来进行设置。在

然后将MyEmitterBaseObserver一起使用,我们现在可以处理丢失和恢复到共享驱动器的连接。在

我认为super().run()不是一个好答案。 我试过很多东西来回答希米的问题,但它并不具体,也没有意义。在

下面是我的答案。 我已经完成了测试。在

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


class Watcher :
    def __init__(self):
        self.observer = Observer()
        print('observer init...')

    def run(self):
        global osv_status
        try :            
            event_handler = MyHandler(patterns=["*.txt"])
            self.observer.schedule(event_handler, Directory, recursive=True)
            self.observer.start()
            osv_status = 1            

        except OSError as ex:
            print("OSError")
            time.sleep(.5)

            if self.observer.is_alive() is True:
                self.observer.stop()
                self.observer.join()
                print("Observer is removed [ ",osv_status," ]")
                osv_status = 2

        except Exception as ex:
            self.logger.exception("Exception ex :{0} ".format(ex))


class MyHandler(PatternMatchingEventHandler):
    def __init__(self,*args, **kwargs):
        super(MyHandler, self).__init__(*args, **kwargs)
        print("MyHandler Init")

    def on_created(self, event): 
        print('New file is created ',event.src_path)

        except Exception as ex:            
            self.logger.exception("Exception ex :{0} ".format(ex))


    def on_modified(self,event):
        print('File is modified ',event.src_path)
        try :
            doing()
        except Exception as ex:            
            self.logger.exception("Exception ex :{0} ".format(ex))


if __name__ == "__main__":
    .....
    osv_status = 0 # 0: ready, 1:start  2: halt
    wch =Watcher()
    wch.run()

    try :
        while(1):
            if is_Connect == False:
                sock_connect()
                print('sock_connect')

            time.sleep(1)
            if os.path.exists(Directory) is False and osv_status == 1:
                wch.observer.stop()
                wch.observer.join()
                print("Observer is removed [ ",osv_status," ]")
                osv_status = 0
            elif os.path.exists(Directory) is True and (osv_status == 0 or osv_status == 2):
                if wch.observer.is_alive() is False:
                    wch =Watcher()
                    wch.run()

相关问题 更多 >