7

その場で解析して対応する必要がある (つまり、部分ツリーを解析する) 必要があるソケットを介して XML ドキュメントを受信して​​います。私が望むのは、そうするためのノンブロッキングメソッドです。これにより、より多くのデータが入ってくるのを待っている間 (スレッド化せずに) 他のことを行うことができます。

読み取りバッファが空のときに反復処理が終了した場合、 iterparse のようなものが理想的です。

context = iterparse(imaginary_socket_file_wrapper)
while 1:
    for event, elem in context:
        process_elem(elem)
    # iteration of context finishes when socket has no more data
    do_other_stuff()
    time.sleep(0.1)

SAXもオプションになると思いますが、私のニーズには iterparse の方が簡単に思えます。何か案は?

アップデート:

スレッドの使用は問題ありませんが、回避したいと思っていたレベルの複雑さが生じます。そのためには非ブロッキング呼び出しが適していると思いましたが、XML の解析が複雑になることがわかりました。

4

3 に答える 3

8

iterparse ソースに飛び込むと、解決策が得られました。以下は、その場で XML ツリーを構築し、終了タグの後の要素を処理する簡単な例です。

import xml.etree.ElementTree as etree

parser = etree.XMLTreeBuilder()

def end_tag_event(tag):
    node = self.parser._end(tag)
    print node

parser._parser.EndElementHandler = end_tag_event

def data_received(data):
    parser.feed(data)

私の場合、twisted からデータを供給することになりましたが、ノンブロッキング ソケットでも動作するはずです。

于 2010-02-16T02:18:32.977 に答える
4

これには、ノンブロッキング ネットワーク I/O と、ストリーム指向の XML パーサーという 2 つのコンポーネントがあると思います。

前者の場合、非ブロッキング ネットワーク フレームワークを選択するか、独自のソリューションを展開する必要があります。Twisted は確かに機能しますが、個人的には、制御フレームワークの反転は私の脳を包み込むのが難しいと感じています。パーサーにフィードするために、コールバックで多くの状態を追跡する必要があるでしょう。このため、私はEventletの方がプログラミングが簡単であると考える傾向があり、この状況には適していると思います。

基本的に、ブロッキング ソケット呼び出しを使用しているかのように (通常のループまたはジェネレーターなどを使用して) コードを記述できます、別のコルーチン (「greenlet」) に生成して自動的にI/O 操作がブロックされる場合に協調的な yield を実行し、他のコルーチンを実行できるようにします。

これにより、コードが通常のブロッキング呼び出しのように構造化されているため、ストリーム指向のパーサーを使用することが再び簡単になります。また、ソケットやその他の I/O (たとえばパーサーなど) を直接処理しない多くのライブラリは、ノンブロッキングにするために特別に変更する必要がないことも意味します。

確かに、Eventlet は少し魔法のようですが、Twisted よりも学習曲線がはるかに簡単であり、フレームワークに合わせてロジックを「裏返し」にする必要がないため、コードがより単純になります。

于 2009-09-23T19:24:28.637 に答える
1

スレッドを使用しない場合は、イベントループを使用して、非ブロッキングソケットをポーリングできます。

asyncoreそのようなものの標準ライブラリモジュールです。TwistedはPython用非同期ライブラリですが、複雑で、おそらくニーズに合わせて少し重いです。

または、multiprocessing非スレッドスレッドの代替手段ですが、2.6を実行していないと思います。

いずれにせよ、スレッドや追加のプロセスを使用するか、同じように複雑な非同期の魔法を織り込む必要があると思います。

于 2009-09-23T18:58:00.757 に答える