asyncore.loop не завершается, когда больше нет соединений
Я следую некоторый пример кода для использования asyncore
здесь, только установив timeout
значение для asyncore.loop
как в следующем полном примере:
import smtpd
import asyncore
class CustomSMTPServer(smtpd.SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, data):
print 'Receiving message from:', peer
print 'Message addressed from:', mailfrom
print 'Message addressed to :', rcpttos
print 'Message length :', len(data)
return
server = CustomSMTPServer(('127.0.0.1', 1025), None)
asyncore.loop(timeout = 1)
Я ожидал, что тайм-аут происходит через 1 секунду, но это не так. Код работает намного дольше, чем одна секунда. Что мне здесь не хватает?
3 ответа
Я действительно не знаю, если timeout
аргумент asyncore.loop()
на самом деле предназначен для тайм-аута вызова функции asyncore.loop()
после указанного времени, но здесь есть квитанция об истечении времени ожидания этой функции по истечении указанного времени (замена строки на asyncore.loop()
в примере кода):
import signal
class TimeoutError(Exception): pass
# define the timeout handler
def handler(signum, frame):
raise TimeoutError()
# set the timeout handler and the signal duration
signal.signal(signal.SIGALRM, handler)
signal.alarm(1)
try:
asyncore.loop()
except TimeoutError as exc:
print "timeout"
finally:
signal.alarm(0)
timeout
аргумент asyncore.loop()
количество времени select.select
звонок будет ждать данных. Если нет данных до timeout
иссякает это будет цикл и вызов select.select
снова.
То же самое для channels
идея. Это не означает открытые розетки, но означает активный asyncore.dispatcher
или же asynchat.async_chat
экземпляров. Если вы хотите остановить цикл, вам нужно вызвать close()
метод на ВСЕХ экземплярах зарегистрирован.
В твоем случае server.close()
закроет экземпляр / канал и удалит его из asyncore
петля. Если больше нет активных каналов, этот цикл завершится сам.
Тайм-аут asyncore.loop() - это тайм-аут для select().
Это бесполезно, потому что при тайм-ауте select () цикл возвращается назад, см. Псевдокод:
while True:
do_something()
select(...)
do_something_else()
Если я выполняю симуляцию с использованием сокетов, защищенных брандмауэром, в моем Python 2.7.3 тайм-аут asyncore.loop() составляет 1 минуту после того, как данные не получены из какого-либо сокета.
Я нашел очень полезным иметь следующий метод в asyncore.dispatcher "subclass":
def handle_error(self):
raise
Таким образом, у меня был "правильный" дамп исключения.
Поскольку я не хотел иметь исключение, позже я изменил его на что-то вроде:
def handle_error(self):
print "Error downloading %s" % self.host
pass
Теперь мой код работает правильно, без исключения.
Я не нашел способа контролировать время ожидания.