2017-11-03 9 views
0

APIがthreading.Threadを使用しているサービスを使用していて、内部にDeferredsを使用したいと思います。デーモンツイストでスレッドを使用したAPIを正しく使用する

標準のPythonモジュールのように実行すると問題はありません。ような何か:

from twisted.internet import reactor 
from outside import ServiceUsingThreadingAndDeferred 

service = ServiceUsingThreadingAndDeferred() 

reactor.listenTCP(port, protocol_factory) 

service.start() 

reactor.run() 

私は -y twistdと、次の.tacを実行する場合、サービスが単純に動作していないものの:

from twisted.application import internet, service 
from outside import ServiceUsingThreadingAndDeferred 

service = ServiceUsingThreadingAndDeferred() 

# Application set-up 
application = service.Application("appName") 
my_server = internet.TCPServer(port, protocol_factory) 
my_server.setServiceParent(application) 

service.start() 

私は後者の場合に問題がメインということだと思いますリアクタースレッドはサービススレッド自体を生成していませんが、なぜそれが最初のケースで起こるのかわかりません...私は回避策としてcallLaterを使用しました:

from twisted.application import internet, service 
from outside import ServiceUsingThreadingAndDeferred 
from twisted.internet import reactor 

service = ServiceUsingThreadingAndDeferred() 

# Application set-up 
application = service.Application("appName") 
my_server = internet.TCPServer(port, protocol_factory) 
my_server.setServiceParent(application) 

reactor.callLater(1, service.start) 

しかし、これに取り組むのが正しい方法かどうかはわかりません。アドバイスはありますか?

+0

自己完結型の、最小限の例ください:http://sscce.org/ –

+0

こんにちは、 ここから例のクローンを作成してください:https://github.com/eigen-value/twisted_and_threading – EigenValue

答えて

0

のGitHubリポジトリから、このクラスは、ツイストのスレッドAPI悪用:非原子炉のスレッドで

class ServiceUsingThreadingAndDeferred(): 
    def __init__(self): 
     pass 

    def start(self): 
     print "3rd party API service starting..." 
     self.run_as_thread() 

    def run_as_thread(self, *args, **kwargs): 
     t = threading.Thread(target=self.run_forever, args=args, kwargs=kwargs) 
     t.daemon = True 
     t.start() 

    def run_forever(self): 
     while 1: 
      print "Doing something remote..." 
      time.sleep(1) 
      now = time.time() 
      if 1 > now % 5 >= 0: 
       self.defer_activity() 

    def defer_activity(self): 
     threads.deferToThread(self._activity) 

ServiceUsingThreadingAndDeferred.run_foreverランを。それはthreads.deferToThreadを呼び出すdefer_activityを呼び出します。非リアクタースレッドでthreads.deferToThreadを呼び出すことはできません。非リアクタスレッドで呼び出すのに安全な約1つのTwisted APIがあります:reactor.callFromThread(リアクタスレッドで実行される引数への呼び出しをスケジュールします)。

working.tacは同じことをしますが、運が良ければ、Twistedのいくつかのバージョンで動作するようです。 callLaterが実装されている非リアクタースレッドでthreads.deferToThreadを呼び出すことによって発生する未定義の動作に依存しています。それが完全に動作するか、Twistedバージョンまたはプラットフォーム間で動作が移植可能であるという保証はありません。

あなたは非原子炉のスレッドから原子炉のスレッドプールを使用する場合は、あなたが何かを記述する必要があります。

from twisted.internet.threads import (
    blockingCallFromThread, 
    deferToThread, 
) 

d = blockingCallFromThread(reactor, lambda: deferToThread(self._activity)) 

しかし、あなたは(DeferreddeferToThreadによって返された)dのいずれかの方法を使用することはできません非反応器の糸のどちらかに入れます。

可能であれば、ServiceUsingThreadingAndDeferredのロジックを書き換えて、リアクタと互換性があるようにしてください。そして、これらのすべてのシナリオを避けることができます。

+0

はありがとうをジャンポール、それは理にかなっている。私が言ったように、そのクラスは、Twistedコンテキスト内で第三者のAPIを実際に「プラグアンドプレイ」しないように、Python標準のスレッドとTwistedスレッドモジュールを使用しています。 とにかくrun_as_threadメソッドをオーバーライドするだけでよいので、私はあなたのアドバイスに従ってください!ありがとうございました – EigenValue

関連する問題