2009-09-22 3 views
7

私は、XML文書を解析し、その場で反応する(つまり、部分木を解析する)必要があるソケットを経由しています。私が望むのは、そうしない非ブロッキングの方法です。そうすれば、より多くのデータが(スレッディングなしで)来るのを待っている間に他のことを行うことができます。読み取りバッファが空だったとき、それは、例えば反復を終了した場合iterparseは理想的であるようにPythonでXMLを解析(ストリーミング)するためのノンブロッキングメソッド

何か:

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を解析する複雑さが増していることがわかりました。

答えて

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) 

私はそれをツイストからのデータを送り終わったが、それはまた、非ブロッキングソケットで動作するはずです。

+0

私は十分にこの答えをupvoteすることはできません – donopj2

+0

ピーターありがとう。私は最終的にあなたの答えのおかげで別の答えを見つけました。私のより精巧な答えを見てください:https://stackoverflow.com/a/44414167/938111 – olibre

1

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

asyncoreは、このようなものの標準ライブラリモジュールです。 Twistedです。 Python用の非同期ライブラリですが、複雑で多分あなたのニーズに少し重いです。

また、multiprocessingはスレッド以外のスレッドの代替ですが、私はあなたが2.6を実行していないと仮定します。

私は、スレッドや余分なプロセスを使わなければならないとか、複雑な非同期の魔法を織りならざるを得ないと思います。

+0

asyncoreはすばらしく見えますが、まだiterparseを別のスレッドに入れるという複雑さを超えないXMLを解析する方法が必要です( –

+0

)。なぜスレッドが出ていたのか分かりませんでした。そのイベントレットは、この場合はスレッドよりも格好良いものの、それほど単純ではありません。あなたが並行/非同期/スレッドの振る舞いをしたいと思えば、私はそれを見て、その複雑さのために価格を支払わなければならないでしょう。 XMLライブラリ(または他のほぼすべてのライブラリ)は、異なる抽象化レベルでよりうまく機能しているため、焼き付けられた種類の機能は搭載されません。 – wbg

4

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

ノンブロッキングネットワークフレームワークを選択するか、独自のソリューションをロールバックする必要があります。ツイストは確かにうまくいくだろうが、私は個人的に脳を包むのが難しいコントロールフレームワークの逆転を見つける。あなたは、おそらく、パーサーにフィードするためにコールバック内の多くの状態を追跡する必要があります。このような理由から、私はEventletがプログラムするのが少し楽になる傾向があり、この状況ではうまくいくと思います。

あなたは別のコルーチン(A "にそれを起動することができますことを除いて、(通常のループまたは発電機または任意のあなたが好きを使用して)ブロッキングソケットコールを使用していたかのように基本的にそれはあなたのコードを書くことができますGreenlet ")を使用して、I/O操作がブロックされたときに自動的に協調歩留まりを実行し、他のコルーチンを実行させることができます。

これは、コードが通常のブロッキングコールのように構成されているため、ストリーム指向のパーサーを使用することになります。また、ソケットやその他のI/O(パーサーなど)を直接処理しないライブラリの多くは、非ブロックであるように特別に修正する必要はありません。ブロックすると、コルーチンが生成されます。

確かEventletは少し魔法ですが、私はあなたがフレームワークに合わせて、「裏返し」あなたのロジックをオンにする必要はありませんので、それはツイストよりもはるかに簡単に学習曲線を持っており、より簡単なコードで結果を見つけます。

+0

Twistedは本当にあなたの頭を上げるのがかなり難しいですが、一度あなたが 'Deferred'sを理解すれば、それは驚くほど強力です。私はイベントレットを簡単に見てきましたが、スレッドに基づいています。これはOPが除外しました。 しかし、なぜスレッドがオプションではなかったのかは分かりませんでした。複雑さの問題がある場合、Eventletは勝利に満ちています。 – wbg

+0

実際、イベントレットはスレッドを必要としませんが、それと直交で互換性があります。それは協調コルーチンを実装する "greenlet"というCエクステンションを使用しています。これはPythonのジェネレータの一般化バージョンと考えることができます。グリーンレットはコントロールを生成し、中止したところからすぐに再開できます。イベントレットは、この機能を使用して、I/O操作がブロックされたときにグリーンレットを自動的に生成し、その後I/Oが完了したときに再開します。実際、それはボンネットの下でツイステッドのような反応炉を使用しますが、グリーンレットは直接それを暴露するのではなく、スケジュールを立てます。 – edarc

+0

TwistedはHTMLとHTTPに集中しているようです。 TwistedをXMLとTCPソケットで使用する例はありますか? –

関連する問題