为什么select.select告诉我它不可读

时间:2018-11-01 09:01:13

标签: python-3.x pipe file-descriptor

以下最小代码的行为似乎不正确。为什么第二个select.select找不到剩余的行。某处有缓冲区吗?如何显示正确的缓冲区?

import select
import os

read, write = os.pipe()
writeable = os.fdopen(write, "w")
readable = os.fdopen(read, "r")
writeable.write("first\n")
writeable.write("second\n")
writeable.flush()
if select.select([readable], [], [], 10)[0][0] == readable:
    print(readable.readline())

print(str(select.select([readable], [], [], 1)))
print(readable.readline())

---结果:

first

([], [], [])
second

1 个答案:

答案 0 :(得分:1)

问题是由于缓冲引起的。我找不到任何具体的文档,但是当您第一次调用readline时,似乎完整的输入已被拉到缓冲区中。

您可以在fdopen中将第三个变量指定为无缓冲,但不允许在文本中抛出

ValueError: can't have unbuffered text I/O

如果将输入设为允许无缓冲I / O的字节流,则可以看到区别(带有注释的更改):

import select
import os

read, write = os.pipe()

# Use a byte stream and add 0 to disable buffering
writeable = os.fdopen(write, "wb", 0)
readable = os.fdopen(read, "rb", 0)

# Write in bytes
writeable.write(b"first\n")
writeable.write(b"second\n")
writeable.flush()

if select.select([readable], [], [], 10)[0][0] == readable:
    print(readable.readline())

print(str(select.select([readable], [], [], 1)))
print(readable.readline())

# Do another check on select.
print(str(select.select([readable], [], [], 1)))

这样做可以给我们输出:

>>>b'first\n'
>>>([<_io.FileIO name=4 mode='rb' closefd=True>], [], [])
>>>b'second\n'
>>>([], [], [])

我猜这是您期望的行为,如果然后从fdopen调用中删除禁用缓冲0变量,

writeable = os.fdopen(write, "wb")
readable = os.fdopen(read, "rb")

您回来了:

>>>b'first\n'
>>>([], [], [])
>>>b'second\n'
>>>([], [], [])

与您的原始示例一样。