2012-01-14 10 views
2

を必要と私はつまり、単に延期を返す既存のツイスト方法にコールバックしてerrbacksを追加することが、最善の方法ではない、「最初」の取り扱いに対処するための最良の方法にいくつかの明確化のためにのDeferredを期待していますそれらを作成するオリジナル延期。Pythonのツイストは、繰延:明確化

具体的な例として、ここでは同じ方法の2バリエーションは、以下のとおりです。 それだけでいくつかのかなり大きなテキストファイルの行数をカウントし、のDeferredのチェーンの出発点として使用されています。

方法1 遅延式はリアクタコールラータ方式で直接起動されるので、このように気分は良くなりません。

def get_line_count(self): 
    deferred = defer.Deferred() 

    def count_lines(result): 
     try: 
      print_file = file(self.print_file_path, "r") 
      self.line_count = sum(1 for line in print_file) 
      print_file.close() 
      return self.line_count 
     except Exception as inst: 
      raise InvalidFile() 

    deferred.addCallback(count_lines) 
    reactor.callLater(1, deferred.callback, None) 
    return deferred 

方法2:繰延よう結果が

def get_line_count(self): 
    deferred = defer.Deferred() 

    def count_lines(): 
     try: 
      print_file = file(self.print_file_path, "r") 
      self.line_count = sum(1 for line in print_file) 
      print_file.close() 
      deferred.callback(self.line_count) 
     except Exception as inst: 
      deferred.errback(InvalidFile()) 

    reactor.callLater(1, count_lines) 
    return deferred 

注意が利用可能な場合 わずかに良い、実際にを解雇されていますまた、これらの両方があることを指摘することができ実際には同期メソッド、潜在的にブロックメソッドがあります(おそらく、 "MaybeDeferred"を使用できます)。 しかし、それは実際に私が混乱する側面の一つです。 方法2については

  1. count_lines方法は、(いくつかの巨大なファイルなどでラインを数えて)非常に遅い場合は、意志、それは潜在的に「ブロック」全体のねじれのアプリ? コールバックとエラーバックとリアクタが一緒に振る舞う(コールバックを素早く実行する必要がある、あるいは遅延自体を返す必要がある)方法については、かなり多くのドキュメントを読んでいますが、この場合は表示されず、 /例など

  2. はそこにいくつかの記事/これらの「最初」のDeferredを作成する最善のアプローチに対処明らかな説明はありますか?私はthese excellent articlesを読んできましたが、彼らは基本的な理解のいくつかで多くの助けをしましたが、私はまだ作品が欠落しているように感じます。コードブロッキングについて

  3. が、これはこのDeferToThread又はreactor.spawnprocessためtypicallケースでしょうか? は私がthis onethis articleのような多くの質問を読んで、私はまだファイルを扱う際に潜在的に大部分が、コードをブロックに対処する方法については100%を確認していないI/Oの

申し訳ありませんがもし、この任意のあまりにも基本的なようだが、私は本当により完全にツイストを使用してハングアップしたい。 (これは、より多くのネットワーク指向の側面のための本当に強力なツールでした)。 ありがとうございました!

答えて

2

はい、正しくあります.Twistedイベントループをブロックしないように、スレッドまたは別のプロセスが必要です。 Deferredsを使用すると、魔法のようにあなたのコードを非ブロックにすることはありません。あなたの質問について:

  1. はい、count_linesが非常に遅い場合は、イベントループをブロックします。それをスレッドに委ねることでこれを解決できます。

  2. 私はTwisteds documentationを使用してDeferredsの仕組みを学習しましたが、あなたはすでにそれを経験していると思います。 database supportの記事は、このライブラリがスレッドを使用して構築されていることを明示しているため、情報でした。これは、同期非同期ギャップをブリッジする方法です。

  3. コールが本当にブロックされている場合は、DeferToThreadが必要です。 Python自体は一種のシングルスレッドなので、一度に1つのスレッドしかPythonバイトコードを実行できません。ただし、作成したスレッドがI/Oでブロックされる場合は、このモデルは正常に動作します。スレッドはグローバルインタプリタロックを解放し、メインスレッドにTwistedイベントループを含む他のPythonスレッドを実行させます。

    コード内に非ブロックI/Oを使用することもできます。これは例えばselectモジュールで行うことができます。その場合、別のスレッドは必要ありません。 Twistedはこの技術を内部的に使用しており、通常のネットワークI/Oを行う場合はこれを考える必要はありません。しかし、あなたが何かエキゾチックなことをしているなら、同じことをすることができるように物事がどのように構築されているか知ることは良いことです。

私は物事を少しはっきりさせることを望む!

+0

すばやく徹底的な返信をいただき、ありがとうございました。 1. 2.この場合、スレッド/スレッドプールアプローチ*が有効です。 –

+0

3.私はGILのためにPythonのスレッドを気にする傾向がありますが、通常は、Twistedイベントを混乱させることなく、ほぼ同時にcount_linesメソッドを実行している3-4スレッドに対処できなければなりませんループ(この方法は小さな「タスク」で使用され、ファイルからのデータをシリアル経由でデバイスに送信します) –

+0

選択モジュールの情報をありがとうございます。これはTwistedのさまざまな種類のリアクタに「関連している」ようです。私はそれをもっと詳しく調べます!実用的には、残念なことにWindowsプラットフォーム上のソケットだけをサポートしています(Windows上でツイストされたシリアルサポートを使用すると、私が持っていた非常に奇妙な制限があります)。 –