Python(Watchdog)- 等待文件正确创建

6 投票
3 回答
7812 浏览
提问于 2025-04-17 20:26

我刚开始学习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 个回答

0

与其用经过的时间来判断,不如直接监控特定类型的文件,这样更简单。你可以使用一个叫做 PatternMatchingEventHandler 的工具里的 patterns 变量。

在你上传或写入的每个文件名后面加上 '.temp',等文件处理完毕后再把它们改回真实的名字。

patterns 设置为只关注 '*.temp' 文件,然后通过 FileSystemMovedEvent 事件来监控这些文件的重命名。你可以用 Handler.on_moved() 方法和 dest_path 值来获取文件的新名字,这样你就能知道文件已经完全写好了。

2

试着在一个循环里读取这个文件:

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
8

为了帮助未来可能看到这个问题的读者,我想说的是,答案似乎是你无法做到这一点。Watchdog 不支持任何功能来判断一个文件是否“完整”,因为 Windows 不允许这样做,而 Watchdog 的设计是为了不依赖于特定系统。

如果你使用的是 Linux 或其某个版本,inotify 可能是个不错的选择。否则,在 Windows 上,我找到的最佳解决方案是:

先上传一个大文件,叫做 bigfile,然后再上传另一个文件,叫 bigfile-complete。当你发现一个文件的名字后面加上 -complete 时,就可以回去处理原来的文件名字。在这种情况下,你的文件会按照顺序添加到监控目录中,顺序是 filefile-complete、file2file2-complete,等等。

你可以监测文件的大小,直到它在一段合适的时间内保持不变。当文件大小长时间没有变化时,你可以合理地认为它已经完成,然后正常处理。

同样地,当一个文件正在分块上传到你的目录时,会不断产生文件修改的 Watchdog 事件。你可以监测这些事件,而不是文件大小,等到这些事件在合理的时间内停止,然后就可以假设文件已经完成,继续处理。

这些解决方案都不是完美的,但这似乎是 Windows 上 Watchdog 的一个固有问题。不幸的是,所谓的“完美”解决方案似乎就是“换到 Linux 并使用 inotify”。

撰写回答