【问题标题】:Python inotify - Execute function upon new file creationPython inotify - 创建新文件时执行函数
【发布时间】:2021-11-20 14:52:06
【问题描述】:

在 python 脚本中,我正在查看来自扫描仪的新文件的目录。目前我的代码只对 IN_CLOSE_WRITE 事件做出反应。我知道正确的方法是注意一个 IN_CREATE 事件,然后是一个 IN_CLOSE_WRITE 事件。

我当前的代码如下所示:

import os
import sys
import logging
import inotify.adapters
import ocrmypdf

def DoOCR(filePath, fileName):
    print("Processing {}".format(fileName))
    try:
       fullPath = os.path.join(filePath, fileName)
       ocrmypdf.ocr(fullPath, fullPath, deskew=True, clean=True, language="deu")
    except ocrmypdf.exceptions.PriorOcrFoundError as err:
       print("Already processed: {0}".format(err))
    except:
       print("Unexpected error:", sys.exc_info()[0])
       raise

if __name__ == '__main__':
    # Setup logging.
    logging.basicConfig(level=logging.DEBUG)
    #logging.basicConfig(level=logging.INFO)

    i = inotify.adapters.Inotify()

    pathToWatch = '/srv/smb/scanneddocs'
    if not os.path.exists(pathToWatch):
        os.mkdir(pathToWatch)

    watchMask = inotify.constants.IN_CREATE | inotify.constants.IN_CLOSE_WRITE

    i.add_watch(pathToWatch, watchMask)
    
    for event in i.event_gen(yield_nones=False):
        (_, type_names, path, filename) = event

        #TODO: Check that a IN_CREATE is followed by a IN_CLOSE_WRITE
        if "IN_CLOSE_WRITE" in type_names:
            print("PATH=[{}] FILENAME=[{}] EVENT_TYPES={}".format(path, filename, type_names))
            name, extension = os.path.splitext(filename)
            print(extension)
            if extension.lower() == ".pdf":
                DoOCR(pathToWatch, filename)
            else:
                print("{} is no PDF file. Skipping...".format(filename))

确保两个事件相继发生的最佳方法是什么?

【问题讨论】:

  • 为什么需要检查IN_CREATE?扫描仪是否也可以覆盖现有文件,而您不想检测到它?
  • 无论如何,你可以为IN_CREATE添加一个检测器,并将文件名放在一个集合中。然后当你得到IN_CLOSE_WRITE 时,检查文件名是否在集合中。
  • @Barmar 如果我只检查 IN_CLOSE_WRITE 修改该特定目录中的文档也会触发该事件。

标签: python inotify


【解决方案1】:

将创建的文件添加到set,然后在收到IN_CLOSE_WRITE 事件时检查集合。

    created_files = set()
    for event in i.event_gen(yield_nones=False):
        (_, type_names, path, filename) = event

        if "IN_CREATE" in type_names:
            created_files.add(filename)
        if "IN_CLOSE_WRITE" in type_names:
            if filename not in created_files:
                continue
            created_files.remove(filename) # remove unneeded item
            print("PATH=[{}] FILENAME=[{}] EVENT_TYPES={}".format(path, filename, type_names))
            name, extension = os.path.splitext(filename)
            print(extension)
            if extension.lower() == ".pdf":
                DoOCR(pathToWatch, filename)
            else:
                print("{} is no PDF file. Skipping...".format(filename))

【讨论】:

  • 您的想法与我已经尝试过的想法非常相似。这里的问题是,只要我观察目录,for 循环就永远不会离开。
  • 如果一段时间内没有事件,可以使用超时退出循环。
  • for event in i.event_gen(yield_nones=False, timeout_s=1):
  • 我想要完成的是目录不断被监视。所以某种循环将是必要的。但也许整个 for 循环构造是完全错误的方式......
  • 如果你想经常看,为什么循环不离开是个问题?也许您可以使用多线程,这样就不会阻塞应用程序的其余部分。
猜你喜欢
  • 1970-01-01
  • 2018-11-21
  • 1970-01-01
  • 2010-10-16
  • 1970-01-01
  • 2013-10-07
  • 2013-05-20
  • 2023-03-27
  • 1970-01-01
相关资源
最近更新 更多