Я работаю над скрученным учебником, чтобы узнать больше python, и, похоже, я столкнулся с дорожным блоком. Функция doRead() ниже - это "обратный вызов" реактора. Я не понимаю, как работает эта часть.
То, как я читаю код, состоит в том, что если bytes += self.sock.recv(1024)
вызвал бы блок, то он достигнет следующей части кода:
if e.args[0] == errno.EWOULDBLOCK:
break
Затем он продолжал бы следующее:
if not bytes:
print 'Task %d finished' % self.task_num
return main.CONNECTION_DONE
else:
msg = 'Task %d: got %d bytes of poetry from %s'
print msg % (self.task_num, len(bytes), self.format_addr())
Сложная часть для меня заключается в том, что если она заблокирована, то переменная байтов ничего бы не содержала и напечатала бы "финиш", но это не так. Или, по крайней мере, это напечатало бы что-то вроде "got 0 bytes", но это также не так. Мне кажется, что когда код встречает блок из вызова recv, он полностью пропускает эту часть. Может кто-нибудь объяснить, почему это происходит?
Результат выглядит примерно так:
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 3: got 10 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 3: got 10 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 3: got 3 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Это целая функция:
def doRead(self):
bytes = ''
while True:
try:
bytes += self.sock.recv(1024)
if not bytes:
break
except socket.error, e: # I don't understand this part
if e.args[0] == errno.EWOULDBLOCK:
break
return main.CONNECTION_LOST
if not bytes:
print 'Task %d finished' % self.task_num
return main.CONNECTION_DONE
else:
msg = 'Task %d: got %d bytes of poetry from %s'
print msg % (self.task_num, len(bytes), self.format_addr())
self.poem += bytes
Весь модуль вставляется здесь: http://pastebin.com/bUnXgbCA
Дело в том, что метод doRead
вызывается только тогда, когда сокет "готов к чтению": либо он имеет некоторые данные на нем, либо все это делается (а затем чтение вернет 0
). Таким образом, решение вашей проблемы не может быть в функции doRead
- все это в коде, вызывающем его только при необходимости.
Этот код находится в реакторе Twisted, к которому экземпляр PoetrySocket
добавляет себя в __init__
(методом реактора addReader
). Если вы хотите понять скрученные механизмы на реальной глубине, вы, кажется, находитесь в нужном месте, кстати, (не считая изучения самих скрученных источников, -).