理解这个多线程恶魔python代码

时间:2014-10-13 14:18:00

标签: python-multithreading python-3.4 python-watchdog

所以我是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秒才能关闭程序。但我可能错了。

1 个答案:

答案 0 :(得分:2)

  1. 请记住守护进程在父进程中运行,嗯, 处理。您需要在该线程中保持父进程处于活动状态 正在执行,否则它将在程序退出时被杀死(和 可能是以不优雅的方式)。那join确保了这个过程 保持活着直到所有线程实际退出;仅仅因为你调用stop并不能保证线程实际上已经完成了执行。 stop是要停止的线程的请求,它不需要在线程终止之前阻塞(也不应该让父线程可以在许多线程上调用stop儿童线程'一次''。

  2. 这纯粹是为了减少CPU消耗。如果您只是在pass中 在那里,CPU会尽可能快地运行while循环。 sleep调用会自动将CPU输出到其他进程,因为它知道它不需要对任何特定条件快速响应。而且你基本上是正确的,它是sleep(1),所以你的最坏情况响应时间约为1秒。

  3. <强>更新

    这是一个为什么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”,而不是真正睡觉。