如何(反复)创建和关闭python twisted factory/reactor的多个实例?
首先,我对这篇文章的标题表示歉意——也许可以用更好的措辞,但我不知道该怎么写!无论如何 我有以下方法分别启动和停止SMTP服务器:如何(反复)创建和关闭python twisted factory/reactor的多个实例?,python,multithreading,twisted,Python,Multithreading,Twisted,首先,我对这篇文章的标题表示歉意——也许可以用更好的措辞,但我不知道该怎么写!无论如何 我有以下方法分别启动和停止SMTP服务器: # ----------------------------------------------------------------------- def startServer(configName = 'default'): try: svrCfg = getServerConfig(configName) st
# -----------------------------------------------------------------------
def startServer(configName = 'default'):
try:
svrCfg = getServerConfig(configName)
startLogger (svrCfg.find('logfile').text)
portal = Portal(SimpleRealm())
checker = InMemoryUsernamePasswordDatabaseDontUse()
checker.addUser("guest", "password")
portal.registerChecker(checker)
serverPort = int(svrCfg.find('port').text)
reactor.listenTCP(serverPort, ConsoleSMTPFactory((portal, svrCfg)))
Thread(target=reactor.run, args=(False,)).start()
# reactor.run()
except twisted.internet.error.CannotListenError, e:
errString = "Cannot start server, port " + svrCfg.find('port').text + " is busy"
log.msg (errString, logLevel=logging.CRITICAL)
except:
log.msg ("Unknown error", logLevel=logging.CRITICAL)
# -----------------------------------------------------------------------
def stopServer():
reactor.callFromThread(reactor.stop)
# -----------------------------------------------------------------------
长期计划是startServer
和stopServer
将成为RobotFramework
关键词。不过现在,转到python命令行,导入源模块(mailserver.py
),只需执行“mailserver.startServer()
”或“mailserver.stopServer()”
等操作就足够了。这对于第一次启动服务器并停止它很好
但是,我们希望能够启动/停止多个并发邮件服务器,监听不同的端口-例如,mailserver.startServer(“p25”)
mailserver.startServer(“p26”)
,mailserver.stopServer(“p25”)
将启动两个实例,然后关闭第一个实例
即使使用我现有的代码,只要重新启动“默认”侦听器就会失败,并出现ReactorNotRestartable错误。。。当然,启动“默认”侦听器,然后启动“p26”侦听器会导致“ReactorAlreadyRunning”错误
有人能就如何避免这些错误提供建议吗?首先,如何获取多个侦听器,其次,如何指定作为“stopServer”的一部分关闭哪个侦听器
(顺便提一下,使用线程以允许startServer退出,以便执行下一个RobotFramework关键字…)
非常感谢
编辑-跟随@JeanPaul Calderone的答案。。。我已成功创建了以下内容:
因此,我调整了代码以支持添加/删除侦听器,如下所示:
def addListener(configName = 'default'):
try:
svrCfg = getServerConfig(configName)
startLogger (svrCfg.find('logfile').text)
portal = Portal(SimpleRealm())
checker = InMemoryUsernamePasswordDatabaseDontUse()
checker.addUser("guest", "password")
portal.registerChecker(checker)
serverPort = int(svrCfg.find('port').text)
listenerPort = reactor.listenTCP(serverPort, ConsoleSMTPFactory((portal, svrCfg)))
runningListeners[configName] = listenerPort
print runningListeners
except twisted.internet.error.CannotListenError, e:
errString = "Cannot start server, port " + svrCfg.find('port').text + " is busy"
log.msg (errString, logLevel=logging.CRITICAL)
except:
log.msg ("Unknown error", logLevel=logging.CRITICAL)
# -----------------------------------------------------------------------
def stopListener(configName = 'default'):
listenerPort = runningListeners[configName]
print listenerPort
listenerPort.stopListening()
listenerPort.connectionLost("Closing listener as requested")
del runningListeners[configName]
# -----------------------------------------------------------------------
Thread(target=reactor.run, args=(False,)).start()
runningListeners={}
我现在当然可以添加和删除多个侦听器。。。然而,当我试图(出于调试目的)从python命令行会话中使用Ctrl-D时,它挂起了——我必须使用Ctrl-Z并终止该作业
所以我意识到反应堆一直在运行,所以我补充说:
def stopReactor():
reactor.callFromThread(reactor.stop)
但现在,当我在Python会话中按Ctrl-D键时:
Unhandled error in Deferred:
Unhandled Error
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1201, in mainLoop
self.runUntilCurrent()
File "/usr/local/lib/python2.7/site-packages/twisted/internet/base.py", line 824, in runUntilCurrent
call.func(*call.args, **call.kw)
File "/usr/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 382, in callback
self._startRunCallbacks(result)
File "/usr/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 490, in _startRunCallbacks
self._runCallbacks()
--- <exception caught here> ---
File "/usr/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 577, in _runCallbacks
current.result = callback(current.result, *args, **kw)
File "/usr/local/lib/python2.7/site-packages/twisted/internet/task.py", line 832, in <lambda>
d.addCallback(lambda ignored: callable(*args, **kw))
File "/usr/local/lib/python2.7/site-packages/twisted/internet/tcp.py", line 1115, in connectionLost
self._closeSocket(True)
File "/usr/local/lib/python2.7/site-packages/twisted/internet/tcp.py", line 123, in _closeSocket
skt = self.socket
exceptions.AttributeError: 'Port' object has no attribute 'socket'
延迟中未处理的错误:
未处理错误
回溯(最近一次呼叫最后一次):
文件“/usr/local/lib/python2.7/site packages/twisted/internet/base.py”,第1201行,在mainLoop中
self.rununtlcurrent()
文件“/usr/local/lib/python2.7/site packages/twisted/internet/base.py”,第824行,在rununtlcurrent中
call.func(*call.args,**call.kw)
文件“/usr/local/lib/python2.7/site packages/twisted/internet/defer.py”,第382行,在回调中
自启动返回(结果)
文件“/usr/local/lib/python2.7/site packages/twisted/internet/defer.py”,第490行,在startRunCallbacks中
self.\u runCallbacks()
--- ---
文件“/usr/local/lib/python2.7/site packages/twisted/internet/defer.py”,第577行,在runCallbacks中
current.result=回调(current.result,*args,**kw)
文件“/usr/local/lib/python2.7/site packages/twisted/internet/task.py”,第832行,在
d、 addCallback(lambda被忽略:可调用(*args,**kw))
文件“/usr/local/lib/python2.7/site packages/twisted/internet/tcp.py”,第1115行,位于connectionLost中
自紧式插座(正确)
文件“/usr/local/lib/python2.7/site packages/twisted/internet/tcp.py”,第123行,在closeSocket中
skt=自插座
exceptions.AttributeError:“端口”对象没有属性“套接字”
有人能告诉我我现在做错了什么吗?你只能启动扭曲反应堆一次。如果您有多个任务要完成,您需要在第一个任务之前启动反应堆,并且只在最后一个任务之后停止。你不能在每项任务前后启动和停止它
您可能会发现管理这种使用模式的反应器很有帮助。放弃最新的问题 最终工作方案如下所示
# -----------------------------------------------------------------------
def addListener(configName = 'default'):
try:
svrCfg = getServerConfig(configName)
startLogger (svrCfg.find('logfile').text)
portal = Portal(SimpleRealm())
checker = InMemoryUsernamePasswordDatabaseDontUse()
checker.addUser("guest", "password")
portal.registerChecker(checker)
serverPort = int(svrCfg.find('port').text)
listenerPort = reactor.listenTCP(serverPort, ConsoleSMTPFactory((portal, svrCfg)))
runningListeners[configName] = listenerPort
print runningListeners
except twisted.internet.error.CannotListenError, e:
errString = "Cannot start server, port " + svrCfg.find('port').text + " is busy"
log.msg (errString, logLevel=logging.CRITICAL)
except:
log.msg ("Unknown error", logLevel=logging.CRITICAL)
def startServer(configName = 'default'):
try:
svrCfg = getServerConfig(configName)
startLogger (svrCfg.find('logfile').text)
portal = Portal(SimpleRealm())
checker = InMemoryUsernamePasswordDatabaseDontUse()
checker.addUser("guest", "password")
portal.registerChecker(checker)
serverPort = int(svrCfg.find('port').text)
reactor.listenTCP(serverPort, ConsoleSMTPFactory((portal, svrCfg)))
Thread(target=reactor.run, args=(False,)).start()
except twisted.internet.error.CannotListenError, e:
errString = "Cannot start server, port " + svrCfg.find('port').text + " is busy"
log.msg (errString, logLevel=logging.CRITICAL)
except:
log.msg ("Unknown error", logLevel=logging.CRITICAL)
# -----------------------------------------------------------------------
def stopListener(configName = 'default'):
listenerPort = runningListeners[configName]
print listenerPort
blockingCallFromThread(reactor, listenerPort.stopListening)
del runningListeners[configName]
# -----------------------------------------------------------------------
def stopReactor():
reactor.callFromThread(reactor.stop)
# -----------------------------------------------------------------------
Thread(target=reactor.run, args=(False,)).start()
runningListeners={}
一如既往地感谢@Jean PaulCalderone。。。我从你的评论中推断(准确地说?!)一旦反应堆运行,我可以添加/删除更多的侦听器,我已经尝试过了。。。这似乎是可行的,但不是100%——我已经编辑了这个问题,将上面修改过的代码包括在内……事实上,在反应堆启动后,几乎所有扭曲的API都能工作(或者更好!)。正如您发现的(我认为)关于
socket
属性的异常是由于调用connectionLost
而不是stopstending
。