2014-05-12 1 views
2

네트워크에 연결된 장치의 upnp 검색을 구현하는 도구가 있습니다.ReactorNotRestartable 오류

나는 스크립트를 작성하고 데이터 그램 클래스를 사용했다.

구현 : 도구에서 검색 버튼을 누를 때마다 해당 upnp 스크립트가 실행되고 도구에 생성 된 상자에 장치가 나열됩니다.

괜찮 았습니다.

하지만 난 다시 스캔 버튼을 누를 때, 그것은 나에게 다음과 같은 오류를 제공합니다 :

Traceback (most recent call last): 
    File "tool\ui\main.py", line 508, in updateDevices 
    upnp_script.main("server", localHostAddress) 
    File "tool\ui\upnp_script.py", line 90, in main 
    reactor.run() 
    File "C:\Python27\lib\site-packages\twisted\internet\base.py", line 1191, in run 
    self.startRunning(installSignalHandlers=installSignalHandlers) 
    File "C:\Python27\lib\site-packages\twisted\internet\base.py", line 1171, in startRunning 
    ReactorBase.startRunning(self) 
    File "C:\Python27\lib\site-packages\twisted\internet\base.py", line 683, in startRunning 
    raise error.ReactorNotRestartable() 
twisted.internet.error.ReactorNotRestartable 
UPnP를 스크립트의

주요 기능 : M-검색 명령을 전송하는 서버 클래스는

def main(mode, iface): 
    klass = Server if mode == 'server' else Client 
    obj = klass 
    obj(iface) 
    reactor.run() 

있다 (upnp) 장치를 발견 할 수 있습니다. 서버 클래스 생성자에서

MS = 'M-SEARCH * HTTP/1.1\r\nHOST: %s:%d\r\nMAN: "ssdp:discover"\r\nMX: 2\r\nST: ssdp:all\r\n\r\n' % (SSDP_ADDR, SSDP_PORT) 

, m-검색을 보낸 후 나는 그것의 제한 사항입니다 beacause를 우리는 원자로를 다시 시작할 수 있다는 것을 발견 구글에서 반응

reactor.callLater(10, reactor.stop) 

를 허리를 구부리하고있다.

http://twistedmatrix.com/trac/wiki/FrequentlyAskedQuestions#WhycanttheTwistedsreactorberestarted 

내가 1 시간보다 더 많은 장치를 스캔 할 수 있어요 및 "안내하시기 바랍니다에 대한 응답이"반응하지 재시작 오류 "

답변

1

을하지 않도록 난 내 코드를 수정하는 방법 나를 인도 해주십시오 어떻게하면 코드를 수정할 수 있습니까? "라고 말하면, 특별히 가이드 할 수있는 코드를 충분히 제공하지 못했기 때문에 스캔/검색에 대한 논리의 (꼬인 부분)을 이해해야합니다.

그러나 "twisted reactor"에 대한 일반 디자인/패턴/정신 모델을 제공하려면 은 프로그램 메인 루프으로 생각하십시오. (어쨌든 그 문제를 내게 명백하게 만드는 것은 reactor에 관한 것입니다 ...)

I.E. 가장 긴 실행중인 프로그램은 트위스트에서 동일한 코드를 더 좋아하는지

def main(): 
    while(True): 
     check_and_update_some_stuff() 
     sleep 10 

같은 형태의 무언가가 : 당신의 main()을 구성하는 무한 루프 "와 같은 반응을 생각하면

def main(): 
    # the LoopingCall adds the given function to the reactor loop 
    l = task.LoopingCall(check_and_update_some_stuff) 
    l.start(10.0) 
    reactor.run() # <--- this is the endless while loop 

을 내 프로그램 "이라면 왜 아무도 반응기를"재시동 "하는 지원을 추가하지 않는 이유를 이해하게 될 것입니다. 왜 무한 루프를 다시 시작 하시겠습니까? 프로그램의 핵심을 멈추는 대신에, 그저 내부 루프 만 남기고 완료된 작업을 외과 적으로 중지해야합니다.

반응기가 작동 중일 때 현재 코드가 "m- 검색 보내기"를 끝없이 계속한다는 것을 암시하는 것 같습니다. 그래서 송신 코드를 변경하여 "send"를 반복하지 않게하십시오. (... 코드를 제공하지 않았기 때문에 이것을 수행하는 방법을 말할 수는 없지만, LoopingCall.stop 메소드를 호출하여 해제 할 수 있습니다 .

의 Runnable 예는 다음과 같다 :

#!/usr/bin/python 

from twisted.internet import task 
from twisted.internet import reactor 
from twisted.internet.protocol import Protocol, ServerFactory 

class PollingIOThingy(object): 
    def __init__(self): 
     self.sendingcallback = None # Note I'm pushing sendToAll into here in main() 
     self.l = None # Also being pushed in from main() 
     self.iotries = 0 

    def pollingtry(self): 
     self.iotries += 1 
     if self.iotries > 5: 
      print "stoping this task" 
      self.l.stop() 
      return() 
     print "Polling runs: " + str(self.iotries) 
     if self.sendingcallback: 
      self.sendingcallback("Polling runs: " + str(self.iotries) + "\n") 

class MyClientConnections(Protocol): 
    def connectionMade(self): 
     print "Got new client!" 
     self.factory.clients.append(self) 

    def connectionLost(self, reason): 
     print "Lost a client!" 
     self.factory.clients.remove(self) 

class MyServerFactory(ServerFactory): 
    protocol = MyClientConnections 

    def __init__(self): 
     self.clients = [] 

    def sendToAll(self, message): 
     for c in self.clients: 
     c.transport.write(message) 


# Normally I would define a class of ServerFactory here but I'm going to 
# hack it into main() as they do in the twisted chat, to make things shorter 

def main(): 
    client_connection_factory = MyServerFactory() 

    polling_stuff = PollingIOThingy() 

    # the following line is what this example is all about: 
    polling_stuff.sendingcallback = client_connection_factory.sendToAll 
    # push the client connections send def into my polling class 

    # if you want to run something ever second (instead of 1 second after 
    # the end of your last code run, which could vary) do: 
    l = task.LoopingCall(polling_stuff.pollingtry) 
    polling_stuff.l = l 
    l.start(1.0) 
    # from: https://twistedmatrix.com/documents/12.3.0/core/howto/time.html 

    reactor.listenTCP(5000, client_connection_factory) 
    reactor.run() 

if __name__ == '__main__': 
    main() 

이 스크립트는 그래서 그냥 설명에 main()self.l.stop()PollingIOThingypolling try 방법과 l 관련된 것들에 초점을 걱정하지 않을 수도 거기에 여분의 cruft에있다 요점.

(이 코드는 SO에서 온다 : 당신이 여분의 비트에 대해 무엇을 알고 싶다면 그 질문을 확인 Persistent connection in twisted)