python - select.select()如何工作?

时间:2012-07-21 09:34:20

标签: python select

背景:

我熟悉select() C函数。我一直在为许多人使用这个功能。大多数(如果不是全部)读取和写入管道,文件等...我必须说我从未使用错误列表,但这不涉及关键问题。

问题:

python select()的行为如下吗?

事实证明,尽管与select()的{​​{3}}接口有关,但python上的select()行为方式不同。似乎select()在文件第一次准备好阅读时返回。如果您读取的文件在其队列中是字节,则调用select()将阻止。但是,如果您在之前调用select()之后再次呼叫select()而未在这两次呼叫之间进行任何读取呼叫,则select()将按预期返回。例如:

import select
# Open the file (yes, playing around with joysticks)
file = open('/dev/input/js0', 'r') 
# Hold on the select() function waiting
select.select([file], [], [])
# Say 16 bytes are sent to the file, select() will return.
([<open file '/dev/input/js0', mode 'r' at 0x7ff2949c96f0>], [], [])
# Call select() again, and select() will indeed return.
select.select([file], [], [])
([<open file '/dev/input/js0', mode 'r' at 0x7ff2949c96f0>], [], [])
# read 8 bytes. There are 8 bytes left for sure. Calling again file.read(8) will empty the queue and would be pointless for this example
file.read(8)
'<\t\x06\x01\x00\x00\x81\x01'
# call select() again, and select() will block
select.select([file], [], [])
# Should it block? there are 8 bytes on the file to be read.

如果这是python中select()的行为,我没关系,我可以处理它。不是我的预期,但它很好,我知道我能做些什么。

但是,如果这不是select()的行为,我会很感激有人告诉我我做错了什么。我读到的关于select()的内容是python doc所说的:“如果read | write | error列表中的任何文件都准备好读取|写入错误,则select()返回。”那没关系,没有谎言。也许问题应该是:

  • 当文件被认为可以在python中读取时?
  • 这是否意味着一个从未被读过的文件?
  • 这是否意味着要读取字节的文件?

2 个答案:

答案 0 :(得分:19)

Python select()作为select()系统调用传递,正如您所期望的那样,但是阻塞它的问题是另一个问题,可能与缓冲有关。只是为了满足自己select()做正确的事情,尝试在文件系统上读/写文件,而不是使用操纵杆等特殊设备。

您可能想要更改open()来电。默认情况下,Pythons open调用将使用缓冲读取,因此即使您执行read(8),它也可能从输入文件中读取更多数据并缓冲结果。您需要将buffering选项设置为open,以便无缓冲地打开操纵杆设备。

建议您尝试:

  • Python默认以文本模式打开文件。处理特殊设备(如操纵杆)时,您可能希望开放moderb
  • 以无缓冲模式打开文件。
  • 如果您要进行基于select的呼叫,请将设备设置为非阻止模式。尝试将os.open()os.O_RDONLY|os.O_NONBLOCK标记一起使用。

答案 1 :(得分:0)

我可以问一个愚蠢的问题 - 你确定还剩下8个字节吗?

设备节点不一定像普通文件一样。可能是您必须在单个read()系统调用中读取整个struct input_event。 (如果你读得不够,其余的就会被扔掉)。有点像数据报套接字上的recvmsg()。