(長い)かなり前に、同時要求が同時に発生するようにマルチスレッド化したWebスパイダーを作成しました。それは私のPythonの若者で、 GIL と、それがマルチスレッドコードのために作成する関連する問題を知る前の日々でした(IE、ほとんどの場合は終了します)シリアル化アップ!)...
このコードを作り直して、堅牢性とパフォーマンスを向上させたいと思います。これを行うには、基本的に2つの方法があります。2.6+では新しい multiprocessing module を使用するか、何らかのリアクター/イベントベースのモデルを使用できます。はるかに単純でエラーが発生しにくいため、後者を使用したいです。
したがって、質問はどのフレームワークが私のニーズに最も適しているかに関するものです。以下は、私がこれまでに知っているオプションのリストです。
見逃したことはありますか?確かに、単純化された非同期ネットワークライブラリのスイートスポットに適合するライブラリがそこになければなりません。
[編集: このページ へのポインタを intgr に感謝します。一番下までスクロールすると、このタスクに何らかの方法で取り組むことを目的とするプロジェクトの本当に素晴らしいリストがあることがわかります。実際には、Twistedの開始以来、物事は実際に進んでいるようです。人々は今では、従来のリアクター/コールバック指向のソリューションよりも co-routine ベースのソリューションを好むようです。このアプローチの利点は、より直接的で直接的なコードです。特に、C++で boost.asio を使用している場合、コールバックベースのコードは設計が困難になる可能性があるため、過去に確かに見つかりました。 -従い、訓練されていない目には比較的目立たない。コルーチンを使用すると、少なくとも少し同期したコードを作成できます。今、私のタスクは、私がこれらの多くのライブラリのどれを気に入っているかを見つけ出し、試してみることです!私は今尋ねたうれしい...]
[編集:この質問をフォローまたはつまずいた人、または何らかの意味でこのトピックを気にかけている人に興味があるかもしれません: 利用可能なツール の現在の状態に関する本当に素晴らしい記事を見つけました]
concurrence Pythonモジュールは、Stackless Pythonマイクロスレッドまたは軽量スレッド用のGreenletsに依存しています。すべてのブロッキングネットワークI/Oは、単一のlibevent
ループを介して透過的に非同期に行われるため、実際の非同期サーバーとほぼ同じくらい効率的です。
この点でEventletに似ていると思います。
欠点は、そのAPIがPythonのsockets
/threading
モジュールとはまったく異なることです。アプリケーションのかなりの部分を書き換える必要があります(または互換性シムレイヤーを記述します)
編集:cogen もあるようですが、これは似ていますが、Python 2.5を使用しています強化されたジェネレーター、コレットの代わりに、Greenlets。これにより、同時実行や他の代替手段よりも移植性が高くなります。ネットワークI/Oは、epoll/kqueue/iocpで直接行われます。
Twistedは複雑です、あなたはそれについて正しいです。ツイストはnot肥大化しています。
ここを見てみると、 http://twistedmatrix.com/trac/browser/trunk/twisted は、組織化された包括的で非常によくテストされたスイート多くのインターネットのプロトコル、および非常に洗練されたネットワークアプリケーションを記述および展開するためのヘルパーコード。肥大化と包括性を混同しないでください。
Twistedのドキュメントは一見すると最もユーザーフレンドリーではないことはよく知られていますが、これは不幸な数の人々を追い払うと信じています。しかし、時間を入れると、Twistedはすごいです(IMHO)。私はやったが、それは価値があることが証明されたので、他の人にも同じことを試してみることをお勧めします。
gevent は eventletのクリーンアップ です。
APIに関しては、意味のある標準ライブラリ(特に、スレッド化およびマルチプロセッシングモジュール)と同じ規則に従います。 Queue や Event のようなおなじみのものがあります。
libevent (update:1.0からのlibev )のみをサポートしますが、最大限に活用しますそのほとんどは、libevent-httpに基づく高速WSGIサーバーを特徴とし、他のほとんどのライブラリのようにスレッドプールを使用するのではなく、libevent-dnを介してDNSクエリを解決します。 (update:1.0 c-aresが非同期DNSクエリを作成するために使用されるため、スレッドプールもオプションです。)
Eventletと同様に、 greenlets を使用してコールバックと遅延を不要にします。
例を確認してください: 複数のURLの同時ダウンロード 、 長いポーリングwebchat 。
本当に 興味深い比較 このようなフレームワークは、NicholasPiëlが彼のブログで編集したものです。読む価値は十分にあります。
これらのソリューションはどれも、GILがCPUの並列処理を妨げるという事実を回避するものではありません。これらは、既にスレッドで使用しているIO並列処理を取得するより良い方法です。 IOを改善できると思う場合は、必ずこれらのいずれかを実行してください。しかし、ボトルネックが結果の処理にある場合は、マルチプロセッシングモジュール以外は何も役に立ちません。
Twistedを肥大化したとは言いませんが、頭を包むのは難しいです。私はいつも「小さなタスク」のために少し簡単なものが欲しかったので、かなり長い間学習に落ち着くことを避けました。
しかし、私はそれでもう少し働いたので、すべてのバッテリーが含まれていることは非常にいいと言わざるを得ません。
私が取り組んだ他のすべての非同期ライブラリは、見た目よりもずっと成熟していません。 Twistedのイベントループは安定しています。
急勾配のツイスト学習曲線をどのように解決するかはよくわかりません。誰かがそれをフォークして、後方互換性の残骸と死んだプロジェクトをすべて削除するなど、いくつかのことをクリーンアップすると役立つかもしれません。しかし、それが成熟したソフトウェアの性質だと思います。
私はいくつかのことにツイストを使い始めました。それの美しさは、ほとんど「肥大化」しているためです。主要なプロトコルのほぼすべてに対応するコネクタがあります。コマンドを受け取ってircサーバーにポストし、それらをメールで送信し、コマンドを実行し、NNTPサーバーから読み取り、Webページの変更を監視するJabberボットを使用できます。悪いニュースは、それがすべてを行うことができ、OPが説明したような単純なタスクでは非常に複雑になることです。 pythonの利点は、必要なものだけを含めることです。そのため、ダウンロードは20 MBになる可能性がありますが、2 MBのライブラリのみを含めることができます(多くの場合)。ツイストでの私の最大の不満は、あなたが自分で持っている基本的なtcpサーバーを超える例が含まれていることです。
pythonソリューションではありませんが、最近ではnode.jsがより多くの牽引力を得るのを見てきました。実際、私は小規模なプロジェクトのためにそれを検討することを検討しましたが、javascriptを聞いたとき私はうんざりします:)
このテーマに関する良い本があります: "Twisted Network Programming Essentials"、Abe Fettig著。この例は、非常にPythonicなコードを記述する方法を示していますが、個人的には、肥大化したフレームワークに基づいているとは思いません。本の解決策を見てください。もしそれらがきれいでなければ、きれいとはどういう意味かわかりません。
私の唯一のエニグマは、Rubyのような他のフレームワークと同じです。心配です、スケールアップしますか?スケーラビリティの問題が発生するフレームワークにクライアントをコミットするのは嫌です。
Whizzer は、pyevを使用する小さな非同期ソケットフレームワークです。主にpyevのため、非常に高速です。若干の変更を加えて、ツイストされた同様のインターフェイスを提供しようとします。
Syncless も試してください。これはコルーチンベースです(したがって、Concurrence、Eventlet、およびgeventに似ています)。 socket.socket、socket.gethostbyname(など)、ssl.SSLSocket、time.sleep、select.selectのドロップイン非ブロッキング置換を実装します。これは速い。 Stackless Pythonおよびlibeventが必要です。 C(Pyrex/Cython)で書かれた必須のPython拡張が含まれています。
synclessの良さを確認します。 libev(libeventのより新しく、よりクリーンでパフォーマンスの良いバージョン)を使用できます。過去にはlibeventほどのサポートはありませんでしたが、開発プロセスはさらに進んでおり、非常に便利です。
シンプルで軽量なHTTPリクエストライブラリが必要な場合は、 nirest 本当に良い
まったく異なるアプローチをとるPyWorksをご覧ください。オブジェクトインスタンスを独自のスレッドで実行し、そのオブジェクトへの関数呼び出しを非同期にします。
クラスにオブジェクトではなくタスクを継承させ、非同期にすると、すべてのメソッド呼び出しはプロキシになります。戻り値(必要な場合)は、Futureプロキシです。
res = obj.method( args )
# code continues here without waiting for method to finish
do_something_else( )
print "Result = %d" % res # Code will block here, if res not calculated yet
PyWorksは http://bitbucket.org/raindog/pyworks にあります。