【问题标题】:pyinotify bug with reading file on creation?pyinotify 在创建时读取文件的错误?
【发布时间】:2009-04-26 14:07:21
【问题描述】:

每次在某个目录中创建新文件时,我都想解析一个文件。为此,我尝试使用pyinotify 设置一个目录来监视IN_CREATE 内核事件,并触发parse() 方法。

这是模块:

from pyinotify import WatchManager,
    ThreadedNotifier, ProcessEvent, IN_CREATE

class Watcher(ProcessEvent):

    watchdir = '/tmp/watch'

    def __init__(self):
        ProcessEvent.__init__(self)
        wm = WatchManager()
        self.notifier = ThreadedNotifier(wm, self)
        wdd = wm.add_watch(self.watchdir, IN_CREATE)
        self.notifier.start()

    def process_IN_CREATE(self, event):
        pfile = self._parse(event.pathname)
        print(pfile)

    def _parse(self, filename):
        f = open(filename)
        file = [line.strip() for line in f.readlines()]
        f.close()
        return file

if __name__ == '__main__':
    Watcher()

问题是_parse返回的列表在被新的文件创建事件触发时是empty,像这样(文件是在另一个窗口中创建的,而watcher.py正在运行): p>

$ python watcher.py
[]

...但奇怪的是,当直接调用时,它在解释器会话中工作。

>>> import watcher
>>> w = watcher.Watcher()
>>> w._parse('/tmp/watch/sample')
['This is a sample file', 'Another line', 'And another...']

为什么会这样?我调试这个东西的最远距离是知道某些东西使 pyinotify 无法正确读取文件。但是……为什么?

【问题讨论】:

  • 除了IN_CREATE,你还应该挂上IN_MODIFY。即pyinotify.IN_CREATE| pyinotify.IN_MODIFY

标签: python linux


【解决方案1】:

也许你想等到文件关闭?

【讨论】:

  • 是的,可能就是这样。但是,我将事件更改为 IN_CLOSE_WRITE,它基本上只会在文件关闭后 触发,但我仍然得到一个空结果。我还尝试在 _parse() 调用之前插入一个简单的 time.sleep(5) ,但它似乎没有帮助,因为实际上根本没有等待。 :-S 有没有办法在 Python 中等待文件关闭?
【解决方案2】:

这里有一些适用于我的代码,内核为 2.6.18、Python 2.4.3 和 pyinotify 0.7.1——您可能使用其中一些版本的不同版本,但重要的是要确保我们是谈论相同的版本,我认为...:

#!/usr/bin/python2.4

import os.path
from pyinotify import pyinotify

class Watcher(pyinotify.ProcessEvent):

    watchdir = '/tmp/watch'

    def __init__(self):
        pyinotify.ProcessEvent.__init__(self)
        wm = pyinotify.WatchManager()
        self.notifier = pyinotify.ThreadedNotifier(wm, self)
        wdd = wm.add_watch(self.watchdir, pyinotify.EventsCodes.IN_CREATE)
        print "Watching", self.watchdir
        self.notifier.start()

    def process_IN_CREATE(self, event):
        print "Seen:", event
        pathname = os.path.join(event.path, event.name)
        pfile = self._parse(pathname)
        print(pfile)

    def _parse(self, filename):
        f = open(filename)
        file = [line.strip() for line in f]
        f.close()
        return file

if __name__ == '__main__':
      Watcher()

当它在终端窗口中运行时,我在另一个终端窗口中运行

echo "ciao" >/tmp/watch/c3

这个程序的输出是:

Watching /tmp/watch
Seen: event_name: IN_CREATE   is_dir: False   mask: 256   name: c3   path: /tmp/watch   wd: 1   
['ciao']

正如预期的那样。所以你能不能试试这个脚本(当然,如果需要,在 hashbang 中修复 Python 版本)并告诉我们你正在使用的 Linux 内核、pyinotify 和 Python 的确切版本,你在这些确切的情况下观察到什么?很可能通过更详细的信息,我们可以准确地确定哪个错误或异常给您带来了问题。谢谢!

【讨论】:

    【解决方案3】:

    正如@SilentGhost 提到的,您可能在将任何内容添加到文件之前读取文件(即您收到的是文件创建而不是文件写入的通知)。

    更新:带有 pynotify tarball 的 loop.py 示例会将 inotify 事件序列转储到屏幕上。要确定您需要触发哪个事件,请启动 loop.py 以监控 /tmp,然后执行您要跟踪的文件操作。

    【讨论】:

    • 请看我的回复。我已将 inotify 事件更改为 IN_CLOSE_WRITE 并且发生了同样的事情。如何等待文件完成写入?谢谢你的帮助。 :)
    • 您的调试已验证您的解析功能有效。事件的流程一定有问题。 pynotify 网站说 pynotify.py 中有 VERBOSE 标志可用于调试。我没有查看它的用法,但启用此标志可能会提供对事件流的更多洞察。您看到预期的事件了吗?
    【解决方案4】:

    我想我通过使用IN_CLOSE_WRITE 事件解决了这个问题。我不确定在那之前发生的事情使它不起作用。

    @Alex:谢谢,我试过你的脚本,但我使用的是更新版本:Python 2.6.1、pyinotify 0.8.6 和 Linux 2.6.28,所以它对我不起作用。

    这绝对是在文件写入之前尝试解析文件的问题,因此感谢 SilentGhost 和 DanM 解决这个问题。

    【讨论】:

    • 我不知道 IN_CLOSE_CREATE 是一个 inotify 事件...您有相关的支持文档吗?
    • @sadmicrowave 抱歉,我想你发现了一个 3 年前的错字。如果我没记错的话,我最终使用了IN_CLOSE_WRITE
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-15
    相关资源
    最近更新 更多