文件轮询变化是如何工作的?

6 投票
1 回答
7411 浏览
提问于 2025-04-16 10:31

问题

我原本以为下面的脚本最多只会打印一个事件,然后就停止(这个脚本只是为了说明问题而写的)。

#!/usr/bin/env python

from select import poll, POLLIN

filename = "test.tmp"

# make sure file exists
open(filename, "a").close()

file = open(filename, "r+")

p = poll()
p.register(file.fileno(), POLLIN)

while True:
    events = p.poll(100)
    for e in events:
        print e
        # Read data, so that the event goes away?
        file.read()

但是,它每秒打印大约70000个事件。为什么会这样呢?

背景

我写了一个类,里面使用了 pyudev.Monitor 类。这个类除了其他功能外,还会使用 poll 对象 来检查通过 fileno() 方法提供的文件描述符是否有变化。

现在我想为我的类写一个单元测试(我知道应该先写单元测试,所以不需要再提醒我),因此我需要为我的模拟 pyudev.Monitor 对象写一个自己的 fileno() 方法,并且我需要控制它,以便触发 poll 对象报告一个事件。正如上面的代码所示,我无法让它停止报告那些似乎不存在的事件!

我在 poll 类中找不到 acknowledge_event() 或类似的方法来让事件消失(我怀疑只有一个事件不知怎么卡住了),在谷歌和这个网站上搜索也没有找到相关信息。我在 Ubuntu 10.10 上使用的是 python 2.6.6。

1 个回答

5

使用管道比使用文件要更有效。你可以试试这个:

#!/usr/bin/env python
import os
from   select import poll, POLLIN

r_fd, w_fd = os.pipe()

p = poll()
p.register(r_fd, POLLIN)

os.write(w_fd, 'X') # Put something in the pipe so p.poll() will return

while True:
    events = p.poll(100)
    for e in events:
        print e
        os.read(r_fd, 1)

这样就能打印出你想要的那个事件。要触发轮询事件,你只需要往可写的文件描述符里写一个字节就行了。

撰写回答