2

「最初の」遅延を処理するための最良の方法、つまり、遅延を返す既存のツイストメソッドにコールバックとエラーバックを追加するだけでなく、それらの元の遅延を作成するための最良の方法について、いくつかの説明を期待しています。

具体的な例として、同じ方法の2つのバリエーションを示します。これは、かなり大きなテキストファイルの行数をカウントするだけで、一連の遅延の開始点として使用されます。

方法1: 遅延はreactor.callLaterメソッドによって直接実行されるため、これはあまり気分が良くありません。

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」を使用できますか?)。しかし、それは実際に私が混乱する側面の1つです。

  1. 方法2の場合、count_linesメソッドが非常に遅い場合(いくつかの巨大なファイルの行を数えるなど)、Twistedアプリ全体を「ブロック」する可能性がありますか?コールバックとエラーバックとreactorがどのように一緒に動作するか(コールバックをすばやく実行するか、遅延を返す必要があるなど)に関するドキュメントをたくさん読みましたが、この場合、私は見ていません。例など

  2. これらの「最初の」延期を作成するための最良のアプローチを扱った記事/明確な説明はありますか?私はこれらの優れた記事を読み、基本的な理解の一部に大いに役立っていますが、それでも私は作品が欠けているように感じます。

  3. コードをブロックする場合、これはDeferToThreadまたはreactor.spawnprocessの一般的なケースですか?私はこの記事やこの記事のような多くの質問を読みましたが、主にファイルi / oを処理するときに、潜在的にブロックされているコードを処理する方法について100%確信がありません。

これのどれかがあまりにも基本的であるように思われるならば申し訳ありませんが、私は本当にツイストをもっと徹底的に使うコツをつかみたいです。(これは、ネットワーク指向のすべての側面にとって非常に強力なツールです)。お時間をいただきありがとうございます!

4

1 に答える 1

2

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

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

  2. Twistedsのドキュメントを使用して、Deferredsがどのように機能するかを学びましたが、あなたはすでにそれを経験していると思います。データベースのサポートに関する記事は、このライブラリがスレッドを使用して構築されていることを明確に示しているため、情報でした。これは、同期と非同期のギャップを埋める方法です。

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

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

それが物事を少し明確にすることを願っています!

于 2012-01-15T00:14:38.627 に答える