【问题标题】:asyncore.loop doesn't terminate when there are no more connections没有更多连接时 asyncore.loop 不会终止
【发布时间】:2013-04-04 06:07:18
【问题描述】:

我正在按照一些示例代码使用asyncorehere,只为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 秒后会发生超时,但事实并非如此。代码运行时间超过一秒。我在这里错过了什么?

【问题讨论】:

  • @pst:计数不是一个选项。不知道会不会事先有零个或多于零个连接。
  • 那就别拐弯抹角了
  • @pst 我不知道你的意思。我的问题是:为什么asyncore.loop() 的超时在指定时间后没有结束函数asyncore.loop()
  • 好吧,考虑一些情况:1) 文档谎称当没有更多开放通道时它将停止运行,2) 文档谎称 timeout 做了什么,3) asyncore没有在选择 4 中使用指定的超时时间)有 are 开放通道。我怀疑如果指定了计数(例如 2),它将很快结束。如果确实如此,那么可能会排除 #2 和 #3。
  • @pst:我不明白你的意思。也许你可以开始用一个清晰​​、简洁和措辞恰当的答案来回答以下问题:asyncore.loop() 中的timeout 参数的目的是什么?

标签: python python-2.7 timeout asyncore


【解决方案1】:

asyncore.loop()timeout 参数是 select.select 调用将等待数据的时间量。如果在timeout 用完之前没有数据,它将循环并再次调用select.select

channels 的想法也是如此。这并不意味着打开套接字,而是意味着活动的asyncore.dispatcherasynchat.async_chat 实例。如果您想停止循环,您必须在注册的 ALL 实例上调用 close() 方法。

在您的情况下,server.close() 将关闭实例/通道并将其从 asyncore 循环中删除。如果没有更多通道处于活动状态,则此循环将自行终止。

【讨论】:

  • 如果asyncore.loop() 阻止了我的代码,我如何调用close 方法?
  • @Alex 您应该在新线程中运行asyncore.loop(),或者在handlers 之一中调用close。我不知道您如何确定何时退出所以如果您告诉我们您如何确定我们可以提供更多帮助。
  • 我一直试图在线程中运行asyncore.loop(),请参阅stackoverflow.com/questions/14483195/…,但我需要弄清楚在哪里以及如何调用close,或者如何以及在哪里修改任何hander方法。如果您知道如何,如果您能在另一个问题中详细说明这一点,我将不胜感激。
  • @Alex 我在链接的问题上发布了答案。如果您需要更多帮助,请在此处发表评论。
【解决方案2】:

我真的不知道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)

【讨论】:

  • 注意:在装有 Python 2.7 的 Windows 上不可用
【解决方案3】:

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

现在我的代码可以正常工作,无一例外。

我没有找到控制超时的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-26
    • 2020-11-17
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    相关资源
    最近更新 更多