Python(Watchdog)- 等待文件正确创建
我刚开始学习Python,想要实现一个好的“文件创建”检测功能。如果我不加上time.sleep(x)
,我的文件处理会出错,因为它们在文件夹里还在“创建”中。(缓冲区没有清空)
我该如何解决这个问题,而不需要每次文件创建时都等x
秒呢?
这是我的代码:
主程序:
while 1:
if len(parser()) > 0: # arguments are valid
if len(parser()) == 3:
log_path = parser()['log_path']
else:
log_path = os.getcwd()
paths = parser()
if paths:
handler = Event_Handler()
observer = Observer()
observer.schedule(handler, paths['src_fld'], True)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
else:
exit(1)
事件处理类:
class Event_Handler(FileSystemEventHandler):
def on_created(self, event):
if not event.is_directory:
time.sleep(1)
正如我所说,如果没有time.sleep(1)
,我尝试处理一个大文件时会失败,因为它还没有完全写入。
3 个回答
与其用经过的时间来判断,不如直接监控特定类型的文件,这样更简单。你可以使用一个叫做 PatternMatchingEventHandler
的工具里的 patterns
变量。
在你上传或写入的每个文件名后面加上 '.temp'
,等文件处理完毕后再把它们改回真实的名字。
把 patterns
设置为只关注 '*.temp'
文件,然后通过 FileSystemMovedEvent
事件来监控这些文件的重命名。你可以用 Handler.on_moved()
方法和 dest_path
值来获取文件的新名字,这样你就能知道文件已经完全写好了。
试着在一个循环里读取这个文件:
def on_created(event):
...
# WAITING FOR FILE TRANSFER
file = None
while file is None:
try:
file = open(event.src_path)
except OSError:
file = None
print("WAITING FOR FILE TRANSFER....")
time.sleep(3)
continue
为了帮助未来可能看到这个问题的读者,我想说的是,答案似乎是你无法做到这一点。Watchdog 不支持任何功能来判断一个文件是否“完整”,因为 Windows 不允许这样做,而 Watchdog 的设计是为了不依赖于特定系统。
如果你使用的是 Linux 或其某个版本,inotify 可能是个不错的选择。否则,在 Windows 上,我找到的最佳解决方案是:
先上传一个大文件,叫做 bigfile,然后再上传另一个文件,叫 bigfile-complete。当你发现一个文件的名字后面加上 -complete 时,就可以回去处理原来的文件名字。在这种情况下,你的文件会按照顺序添加到监控目录中,顺序是 file、file-complete、file2、file2-complete,等等。
你可以监测文件的大小,直到它在一段合适的时间内保持不变。当文件大小长时间没有变化时,你可以合理地认为它已经完成,然后正常处理。
同样地,当一个文件正在分块上传到你的目录时,会不断产生文件修改的 Watchdog 事件。你可以监测这些事件,而不是文件大小,等到这些事件在合理的时间内停止,然后就可以假设文件已经完成,继续处理。
这些解决方案都不是完美的,但这似乎是 Windows 上 Watchdog 的一个固有问题。不幸的是,所谓的“完美”解决方案似乎就是“换到 Linux 并使用 inotify”。