在我的应用中,我需要查看目录中的新文件。流量非常大,每秒将至少出现数百个新文件。目前,我正在使用这种想法的忙循环:
while True:
time.sleep(0.2)
if len(os.listdir('.')) > 0:
# do stuff
运行分析后,我发现睡眠中花费了大量时间,我想知道是否应该将其更改为使用轮询。
我正在尝试使用select
中的可用类之一来轮询目录,但是我不确定它是否确实有效,或者我是否做错了。
我在目录中得到一个fd:
fd = os.open('.', os.O_DIRECT)
然后,我尝试了几种方法来查看目录何时更改。例如,我尝试过的一件事是:
poll = select.poll()
poll.register(fd, select.POLLIN)
poll.poll() # returns (fd, 1) meaning 'ready to read'
os.read(fd, 4096) # prints largely gibberish but i can see that i'm pulling the files/folders contained in the directory at least
poll.poll() # returns (fd, 1) again
os.read(fd, 4096) # empty string - no more data
为什么poll()表现得像有更多信息要阅读?我认为只有在目录中发生某些更改时,它才会这样做。
我是否正在尝试这样做?
如果没有,while True: look for changes
还有其他更好的选择吗?
运行分析后,我发现睡眠中花费了大量时间,我想知道是否应该将其更改为使用轮询。
看起来您已经do同步轮询,通过定期检查状态)。不必担心sleep
中的“花费”时间,它不会占用CPU时间。它只是将控制权传递给操作系统,该操作系统在请求的超时后唤醒进程。
您可以考虑使用一个侦听操作系统提供的文件系统更改通知的库的异步事件循环,但是首先考虑在这种特殊情况下它是否给您带来真正的好处。
FreeBSD以及Mac OS X提供了称为kqueue的inotify类似物。在FreeBSD机器上输入man 2 kqueue以获得更多信息。对于Freebsd上的kqueue,您可以在http://people.freebsd.org/~dwhite/PyKQueue/处使用PyKQueue,但是很遗憾,该队列没有得到积极维护,因此您的行驶里程可能会有所不同。
为什么不对其中一个库使用Python包装器来监视文件更改,例如gamin或inotify(搜索pyinotify,我只能以新用户身份发布一个超链接...)-可以确保更快,使用内核接口已经为您完成了C级的底层工作...
您可能想看一下select.kqueue-我没有用过,但是kqueue是BSD下正确的接口,我相信这样您就可以监视文件/目录,并且仅在它们更改时才被回调] >
我已经编写了一个库和一个外壳程序工具,应该为您处理这个问题。
如果您的系统具有select.kqueue(),这是解决此问题的好方法,例如: