0

我的 Python 程序需要从多个不同的文件描述符中多路读取。其中一些是子进程的 stdout/stderr 描述符;inotify其他是与调用关联的文件描述符。

我的问题是能够在select(). 根据文档select()报告已准备好写入的套接字“保证不会阻塞最多 PIPE_BUF 字节的写入”。

我认为读取没有这样的保证是有意义的,因为select()报告内核管道缓冲区中有数据等待准备好并不意味着您可以继续执行 to .read(socket.PIPE_BUF),因为那里可能只有几个字节。

这意味着当我调用read()套接字时,我可以得到实际上是死锁,因为一些子进程很少产生输出。

有没有办法解决?我目前的解决方法是调用readline()它,我很幸运,我从中读取的所有内容都有逐行输出。从这样的管道读取时是否select()有任何用处,因为无法知道您可以在不阻塞的情况下安全地读取多少字节?

[1] 我知道这与 O_NONBLOCK 套接字不同

4

2 回答 2

3

可以继续read每个管道和套接字:您将获得现在可用的任何数据:

>>> import os
>>> desc = os.pipe()
>>> desc
(3, 4)
>>> os.write(desc[1], 'foo')
3
>>> os.read(desc[0], 100)
'foo'
>>> os.read(desc[0], 100)

[挂在这里,因为没有可用的输入,用 ^C 打断]

...
KeyboardInterrupt
>>> os.write(desc[1], 'a')
1
>>> os.read(desc[0], 100)
'a'
>>> 
于 2013-03-23T10:12:00.803 回答
0

作为替代方案,我遇到了完全相同的问题,并通过使用readline(1)并将其附加到内部缓冲区来解决它,直到 readline 返回一个我对标记感兴趣的字符(换行符、空格等)。

更多细节:我调用select()了一个文件描述符,然后调用readline(1)了 select 返回的任何文件描述符,将该字符附加到缓冲区,并重复直到 readline 返回我想要的。然后我返回我的缓冲区,清除它并继续前进。顺便说一句,我还返回了一个布尔值,它让调用方法知道我返回的数据是否因为读取错误而为空,只是因为它没有完成。

我还实现了一个可以在超时时进行标记的版本。如果我一直在缓冲 x 毫秒而没有找到换行符或 EOF,请继续并返回缓冲区。

我目前正在尝试找出是否有办法询问文件描述符它有多少字节等待读取,然后readline([that many bytes])...

希望有帮助。

于 2013-11-19T16:53:42.650 回答