我按照一些示例代码在这里使用asyncore
,只为asyncore.loop
设置了一个timeout
值,如以下完整示例所示:
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 秒后会发生超时,但事实并非如此。代码运行的时间要长得多,超过一秒。我在这里错过了什么?
asyncore.loop()
timeout
参数是select.select
调用等待数据的时间量。如果在timeout
用完之前没有数据,它将循环并再次调用select.select
。
channels
的想法也是如此。这并不意味着打开套接字,而是表示活动asyncore.dispatcher
或asynchat.async_chat
实例。如果要停止循环,则必须在所有注册的实例上调用 close()
方法。
在您的情况下server.close()
将关闭实例/通道并将其从asyncore
循环中删除。如果没有更多通道处于活动状态,则此循环将自行终止。
我真的不知道asyncore.loop()
的timeout
参数是否真的是为了在指定时间后使函数调用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)
asyncore.loop() 的超时是 select() 的超时。
它没有用,因为当 select() 超时时,它会循环回来,请参阅伪代码:
while True:
do_something()
select(...)
do_something_else()
如果我使用防火墙套接字进行模拟,在我的 Python 2.7.3 asyncore.loop() 中,在某个套接字没有收到数据后 1 分钟超时。
我发现在asyncore.dispatcher"子类"中使用以下方法非常有用:
def handle_error(self):
raise
通过这种方式,我有"适当的"异常转储。
因为我不想有例外,后来我把它改成这样:
def handle_error(self):
print "Error downloading %s" % self.host
pass
现在我的代码工作正常,无一例外。
我没有找到控制超时的方法。