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

Теперь мой код работает правильно, без исключения.

Я не нашел способа контролировать время ожидания.

Другие вопросы по тегам