Подтвердить что ты не робот

Python - Как работает select.select()?

История:

Я знаком с функцией select() C. Я использую эту функцию для многих purpouses. Большинство из них, если не все, для чтения и записи на трубы, файлы и т.д. Я должен сказать, что я никогда не использовал список ошибок, но это не связано с ключевым вопросом.

Вопрос:

Выполняет ли python select() следующее:

Оказывается, что select() на python ведет себя иначе, несмотря на простой интерфейс с C 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.

Если это поведение select() в python, я в порядке, я мог бы справиться с этим. Не то, что я ожидал, но, но это прекрасно, я знаю, что я могу с этим сделать.

Но если это не поведение select(), я был бы признателен, если бы кто-то сказал мне, что я делаю неправильно. То, что я читал о select(), - это то, что говорит python doc: "select() возвращает, если любой файл в списке read | write | error готов к чтению | write | error.". Это нормально, там нет лжи. Возможно, вопросы должны быть:

  • Когда файл считается готовым для чтения в python?
  • Означает ли это файл, который никогда не читался?
  • Означает ли это файл с байтами для чтения?
4b9b3361

Ответ 1

Python select() передается как системный вызов select(), как вы ожидаете, но проблема с блокировкой - это другая проблема, вероятно, связанная с буферизацией. Просто чтобы убедиться, что select() делает правильные вещи, попробуйте прочитать/записать файл в файловой системе, а не использовать специальное устройство, такое как джойстик.

Вероятно, вы захотите изменить свой вызов open(). Pythons open по умолчанию будет использовать буферизованные чтения, поэтому даже если вы выполните read(8), скорее всего, прочитайте больше данных из входного файла и буферизировать результаты. Вам нужно установить опцию buffering на open, чтобы устройство джойстика было открыто без буфера.

Предложения для вас:

  • Python по умолчанию открывает файлы в текстовом режиме. Вероятно, вы хотите, чтобы open mode был rb при работе со специальными устройствами, такими как джойстик.
  • Откройте файл в небуферизованном режиме.
  • Установите устройство в неблокирующий режим, если вы собираетесь выполнять вызовы select. Попробуйте использовать os.open() с флагами os.O_RDONLY|os.O_NONBLOCK.

Ответ 2

Могу ли я задать глупый вопрос - уверены ли вы, что на самом деле осталось 8 байтов?

Узлы устройств не обязательно ведут себя как обычные файлы. Возможно, вам нужно прочитать весь struct input_event в одном системном вызове read(). (И если вы недостаточно читаете, остальные отбрасываются). Немного напоминает recvmsg() в сокетах датаграмм.