python select.select () в Windows

Я тестирую штамп UDP с помощью кода отсюда . Он работает на Linux, но сообщает об ошибке в Windows. Вот фрагмент кода, где происходит ошибка:

while True: rfds, _, _ = select([0, sockfd], [], []) # sockfd is a socket if 0 in rfds: data = sys.stdin.readline() if not data: break sockfd.sendto(data, target) elif sockfd in rfds: data, addr = sockfd.recvfrom(1024) sys.stdout.write(data) 

И сообщение об ошибке:

 Traceback (most recent call last): File "udp_punch_client.py", line 64, in <module> main() File "udp_punch_client.py", line 50, in main rfds, _, _ = select([0, sockfd], [], []) select.error: (10038, '') 

Я знаю, что эта ошибка имеет какое-то отношение к реализации select в Windows, и все цитируют это:

Примечание. Файловые объекты в Windows неприемлемы, но сокеты. В Windows основная функция select () предоставляется библиотекой WinSock и не обрабатывает дескрипторы файлов, которые не происходят из WinSock.

Поэтому у меня возникли два вопроса:

  1. Что означает 0 в [0, sockfd] ? Это какой-то часто используемый метод?
  2. Если select работает только с socket в Windows, как сделать код Windows совместимым?

Спасибо.

3 Solutions collect form web for “python select.select () в Windows”

К сожалению, select не поможет вам обрабатывать stdin и сетевые события в одном потоке, так как select не может работать с потоками в Windows. То, что вам нужно, это способ читать stdin без блокировки. Вы можете использовать:

  1. Дополнительная нить для stdin . Это должно работать нормально и быть самым простым способом выполнить эту работу. Поддержка потоков Python вполне подходит, если вам нужно только ожидание событий ввода-вывода.
  2. Подобный грибовидному механизму, как и в gevent , поддерживает исправления потоков и большую часть функций ввода-вывода стандартной библиотеки, чтобы предотвратить их блокирование. Существуют также библиотеки, такие как twisted (см. Комментарии), которые предлагают неблокирующий файловый ввод-вывод. Этот способ является наиболее последовательным, но для этого требуется написать все приложение, используя стиль, соответствующий вашей структуре ( twisted или gevent , разница не значительна). Тем не менее, я подозреваю, что twisted обертки не способны на асинхронный ввод из stdin в Windows (совершенно уверен, что они могут сделать это на * nix, поскольку, вероятно, они используют один и тот же select ).
  3. Какой-то другой трюк. Однако большинство возможных трюков довольно уродливые.

Как следует из ответа, я создаю еще один поток для обработки входного потока, и он работает. Вот модифицированный код:

 sock_send = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) def send_msg(sock): while True: data = sys.stdin.readline() sock.sendto(data, target) def recv_msg(sock): while True: data, addr = sock.recvfrom(1024) sys.stdout.write(data) Thread(target=send_msg, args=(sock_send,)).start() Thread(target=recv_msg, args=(sockfd,)).start() 

Мой ответ – вопрос одновременно: я нашел telnet.py в сети, реализованном следующим кодом:

 # telnet program example in python (2.7.x) import socket, select, string, sys #main function if __name__ == "__main__": if(len(sys.argv) < 3) : print 'Usage : python telnet.py hostname port' sys.exit() host = sys.argv[1] port = int(sys.argv[2]) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(2) # connect to remote host try : s.connect((host, port)) except : print 'Unable to connect' sys.exit() print 'Connected to remote host' while 1: socket_list = [sys.stdin, s] print socket_list; # Get the list sockets which are readable read_sockets, write_sockets, error_sockets = select.select(socket_list , [], []) for sock in read_sockets: #incoming message from remote server if sock == s: data = sock.recv(4096) if not data : print 'Connection closed' sys.exit() else : #print data sys.stdout.write(data) #user entered a message else : msg = sys.stdin.readline() s.send(msg)# telnet program example 

Как ни странно, этот код не работает под Windows (потому что select не работает на stdin FD в реализации Windows Winsock2)

Предлагаемое решение относится к примеру UDP, и оно выглядит несколько иначе. Кто-нибудь знает решение для преобразования вышеуказанного telnet.py в многопоточную операцию?

Спасибо.

  • Python - Как проверить, используется ли файл другим приложением?
  • Настройка файла pylint config.rc по умолчанию в Windows
  • Функциональность Readline для окон с помощью python 2.7
  • Ошибка Selenium 3.0.2 с Firefox 50: у исполняемого файла могут быть неправильные разрешения
  • Установка pzmq с помощью Cygwin
  • AttributeError: функция GetConsoleScreenBufferInfoEx не найдена
  • Интерфейс USB в Python
  • VLC: Ошибка импорта без модуля с именем appscript
  • Python - лучший язык программирования в мире.