我试图了解如何在Python中正确使用错误处理。 我正在使用看门狗在网络连接的光盘中寻找我的朋友。光盘暂时断开连接,然后再次连接,然后弹出错误。 “线程Thread-2中的异常:”
我有一个错误处理程序,但是我不确定我做的是否正确。
我是否应该在Observer.schedule步骤再尝试一次?
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()
答案 0 :(得分:0)
好吧,我在评论中提到的sys.excepthook
方法目前尚不可行。 bug已有十多年的历史,它使从threading.Thread
派生的线程忽略sys.excepthook
。该错误的消息线程中概述了一些变通办法,但我急于发布采用变通办法的答案,尤其是因为此臭虫似乎终于可以解决python 3.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)
快速浏览一下源代码,所有观察者似乎都从EventDispatcher.run()
继承了run
,因此您甚至可以省略包装器并直接重新实现该方法
class CustomObserver(Observer):
def run(self):
while self.should_keep_running():
try:
self.dispatch_events(self.event_queue, self.timeout)
except queue.Empty:
continue
except OSError:
time.sleep(.5)
但是,我的包装盒中没有安装该软件包,因此这些东西未经测试;您可能需要四处弄弄才能继续进行。
哦,请确保将OSError
*替换为您情况下实际引发的任何异常类:)
修改:
*根据下面的@HenryYik的评论,网络驱动器断开连接似乎在Windows系统上引发了OSError
(WinError 64:ERROR_NETNAME_DELETED)。我发现在这种情况下UNIX风格的操作系统可能会引发相同类型的异常,因此我更新了代码片段,现在使用OSError
代替了我最初使用的FileNotFoundError
。
答案 1 :(得分:0)
我认为super().run()
不是一个好的答案。
我已经用shmee的答案尝试了很多事情,但这并不是具体而毫无意义的。
以下是我的答案。 我已经完成了测试。
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()
答案 2 :(得分:0)
我还将其发布在相关主题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
中的异常。为了在重新连接后继续运行,看门狗需要重新设置目录句柄,我们可以使用self.on_thread_start()
进行设置。
然后将MyEmitter
与BaseObserver
一起使用,我们现在可以处理丢失和恢复与共享驱动器的连接。