Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何(反复)创建和关闭python twisted factory/reactor的多个实例?_Python_Multithreading_Twisted - Fatal编程技术网

如何(反复)创建和关闭python twisted factory/reactor的多个实例?

如何(反复)创建和关闭python twisted factory/reactor的多个实例?,python,multithreading,twisted,Python,Multithreading,Twisted,首先,我对这篇文章的标题表示歉意——也许可以用更好的措辞,但我不知道该怎么写!无论如何 我有以下方法分别启动和停止SMTP服务器: # ----------------------------------------------------------------------- def startServer(configName = 'default'): try: svrCfg = getServerConfig(configName) st

首先,我对这篇文章的标题表示歉意——也许可以用更好的措辞,但我不知道该怎么写!无论如何

我有以下方法分别启动和停止SMTP服务器:

    # -----------------------------------------------------------------------

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