pyinotify在文件创建时读取的bug?

3 投票
4 回答
1682 浏览
提问于 2025-04-15 11:15

我想要在某个文件夹里每次新文件创建时都能解析这个文件。为此,我正在尝试使用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返回的列表是空的,就像这样(在运行watcher.py的同时,文件是在另一个窗口创建的):

$ python watcher.py
[]

...但奇怪的是,当我在解释器中直接调用时,它却能正常工作。

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

这到底是怎么回事呢?我调试到现在,只知道有某种原因导致pyinotify没有正确读取文件。但是...为什么会这样呢?

4 个回答

1

正如@SilentGhost提到的,你可能是在文件内容还没添加之前就读取了这个文件(也就是说,你收到的是文件创建的通知,而不是文件写入的通知)。

更新:使用pynotify的loop.py示例会把一系列的inotify事件显示在屏幕上。要确定你需要关注哪个事件,可以启动loop.py来监控/tmp目录,然后进行你想要跟踪的文件操作。

1

这里有段代码在我的系统上能正常运行,我的系统使用的是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']

结果是我预期的。所以请你试试这个脚本(如果需要的话,记得修改开头的Python版本),并告诉我们你使用的Linux内核、pyinotify和Python的具体版本,以及在这种情况下你观察到了什么?如果能提供更详细的信息,我们可能能找出是什么bug或者异常导致你遇到的问题。谢谢!

3

也许你想等文件关闭后再进行操作?

撰写回答