Почему select.select говорит мне, что он не читается - PullRequest
0 голосов
/ 01 ноября 2018

Там поведение следующего минимального кода кажется некорректным. Почему второй 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 голосов
/ 01 ноября 2018

Проблема связана с буферизацией. Я не смог найти какую-либо конкретную документацию, но похоже, что при первом вызове readline.

весь ввод данных помещается в буфер.

Вы можете указать отсутствие буферизации в качестве третьей переменной в fdopen, но это не разрешено для текста, выбрасывая

ValueError: can't have unbuffered text 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'
>>>([], [], [])

Я думаю, это поведение, которое вы ожидали, и если вы затем удалите переменную отключить буферизацию 0 из вызовов fdopen,

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

вы вернетесь:

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

Как в вашем первоначальном примере.

...