所以我是python的初学者,正在处理文件系统事件处理程序。我遇到了看门狗api,在那里我看到了一个我无法理解的多线程代码。
以下是在其网站上发布的代码:
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)
except KeyboardInterrupt:
observer.stop()
observer.join()
此代码运行无限循环并侦听某个文件夹并记录控制台的内容。我怀疑是代码的底部。
所以你开始观察者。然后让它继续无限循环,直到完成一些按键操作。我假设在“observer.start()”代码中的某个地方,他们也设置daemon = True。在某些按键操作时,程序将耗尽循环并停止观察者。在watchdog的api中,stop()的定义表示它会停止守护程序线程。
1)然后它执行join()。但这次加入的必要性是什么。我已经停止了守护程序线程。不是join()意味着等待所有线程停止然后然后才退出程序。我可以从代码中删除join()。删除后,我的程序仍能正常运行。
2)我也不明白while循环中需要sleep(1)。如果我在那里放一个“通过”声明会发生什么。我假设while循环将消耗更多的资源???我们将睡眠时间设置为1秒而不是2-3秒的原因是因为在最坏的情况下,用户可能需要等待2-3秒才能关闭程序。但我可能错了。
答案 0 :(得分:2)
请记住守护进程在父进程中运行,嗯,
处理。您需要在该线程中保持父进程处于活动状态
正在执行,否则它将在程序退出时被杀死(和
可能是以不优雅的方式)。那join
确保了这个过程
保持活着直到所有线程实际退出;仅仅因为你调用stop
并不能保证线程实际上已经完成了执行。 stop
是要停止的线程的请求,它不需要在线程终止之前阻塞(也不应该让父线程可以在许多线程上调用stop
儿童线程'一次''。
这纯粹是为了减少CPU消耗。如果您只是在pass
中
在那里,CPU会尽可能快地运行while循环。 sleep
调用会自动将CPU输出到其他进程,因为它知道它不需要对任何特定条件快速响应。而且你基本上是正确的,它是sleep(1)
,所以你的最坏情况响应时间约为1秒。
<强>更新强>
这是一个为什么join
很重要的例子。假设以下内容在线程中运行:
while not self.stop: # self.stop is set to True when stop() is called
...
self.results.append(item) # do some stuff that involves appending results to a list
with open('~/output.txt', 'w') as outfile:
outfile.write('\n'.join(str(item) for item in item))
调用stop
时,while循环将终止,结果文件将打开并开始写入。如果未调用join
,则进程可能会在write
操作完成之前终止,这将导致损坏的结果。 join
确保父线程等待此写入完成。它还确保进程实际等待整个迭代完成while循环;如果没有join
,您不仅可以错过文件写入,还可以在while
块的中间终止。
但是,如果[{1}}调用它的帖子在stop
终止后没有做任何事情,while
会立即有效返回,所以基本上会变成NOP。< / p>
更新2:
对于睡眠呼叫,某些事件(例如join
)可能会冒出父进程的ctrl+c
调用。因此,在这种特殊情况下,睡眠的长度并不重要。将它设置为1秒大多只是惯例,以明确表示你基本上是在做“屈服CPU”,而不是真正睡觉。