私にとって、これは実際にはかなり単純です:
サブプロセスのオプション:
subprocess
ある他の実行ファイルを実行するために、それは周りの基本的ラッパーだ--- os.fork()
とos.execve()
オプションの配管のためのいくつかのサポートを(にし、サブプロセスからパイプを設定する。もちろん、あなた可能性のある他のプロセス間通信(IPC)などのソケットなどのメカニズム、またはPOSIXまたはSysV共有メモリですが、呼び出すプログラムがサポートするインターフェイスとIPCチャネルに制限されます。
一般的に、subprocess
同期的に使用します-外部ユーティリティを呼び出して、その出力を読み取るか、その完了を待機します(おそらく、一時ファイルから結果を読み取るか、データベースに結果をポストした後)。
ただし、何百ものサブプロセスを生成してポーリングすることができます。私自身のお気に入りのユーティリティクラスはまさにそれを行います。
最大の欠点のsubprocess
モジュールは、I / Oのサポートは、一般的にブロックしていることです。これを修正するためのドラフトPEP-3145がPython 3.xの将来のバージョンと代替のasyncprocにあります(これは、あらゆる種類のドキュメントやREADMEではなく、ダウンロードにつながる警告です)。またfcntl
、Popen
PIPEファイル記述子を直接インポートして直接操作することは比較的簡単です。ただし、これがUNIX以外のプラットフォームに移植可能かどうかはわかりません。
(更新:2019年8月7日:Python 3によるayncioサブプロセスのサポート:asyncioサブプロセス)
subprocess
サポートを扱うほとんどないイベントがある ... かかわらず、使用できるsignal
モジュールとプレーンな古い学校のUNIX / Linuxの信号を---それがあったように、そっと自分のプロセスを殺します。
マルチプロセッシングオプション:
multiprocessing
これは、既存の(Python)コード内で関数を実行するためのもので、このプロセスファミリー間のより柔軟な通信をサポートします。特に、可能な場合multiprocessing
はモジュールのQueue
オブジェクトを中心にIPC を構築するのが最善ですが、Event
オブジェクトやその他のさまざまな機能を使用することもできます(その一部は、おそらくmmap
サポートが十分なプラットフォームでのサポートを中心に構築されています)。
Pythonのmultiprocessing
モジュールは、GPython(グローバルインタープリターロック)にもかかわらずCPythonが複数のCPU /コア間で処理をスケーリングできるようにするのと 非常によく似たインターフェースと機能を提供することを目的としていthreading
ます。これは、OSカーネルの開発者が行ったすべてのきめ細かなSMPロックおよび一貫性の取り組みを活用します。
スレッドオプション:
threading
あるI / Oが結合しているアプリケーションのかなり狭い範囲について(複数のCPUコアを横切ってスケールする必要はありません)と極めて低いレイテンシから利益およびプロセス対(共有コアメモリで)スレッド切り替えのオーバーヘッド切替/コンテキストの切り替え。Linuxでは、これはほとんど空のセットです(Linuxプロセスの切り替え時間は、スレッドの切り替えに非常に近いです)。
threading
Pythonには2つの大きな欠点があります。
もちろん、1つは実装固有です---ほとんどがCPythonに影響します。それがGILです。ほとんどの場合、ほとんどのCPythonプログラムは3つ以上のCPU(コア)の可用性の恩恵を受けず、多くの場合、パフォーマンスはGILロック競合の影響を受けます。
実装固有ではない大きな問題は、スレッドが同じメモリ、シグナルハンドラー、ファイル記述子、および特定の他のOSリソースを共有することです。したがって、プログラマーは、オブジェクトのロック、例外処理、および微妙であり、プロセス全体(スレッドのスイート)を強制終了、停止、またはデッドロックする可能性のあるコードの他の側面に非常に注意する必要があります。
比較すると、multiprocessing
モデルは各プロセスに独自のメモリ、ファイル記述子などを提供します。それらのいずれかでのクラッシュまたは未処理の例外はそのリソースのみを殺し、子プロセスまたは兄弟プロセスの消失のロバストな処理はデバッグよりもはるかに簡単です。スレッドの同様の問題を修正または回避します。
- (注:NumPy
threading
などの主要なPythonシステムでの使用は、ほとんどの独自のPythonコードよりもGILの競合による影響がかなり少ない可能性があります。これは、それらがそうするように特別に設計されているためです; NumPyのネイティブ/バイナリ部分、たとえば、それが安全なときにGILを解放します)。
ツイストオプション:
Twistedがエレガントで理解するのが非常に難しいもう1つの代替手段を提供していることも注目に値します。基本的に、Twistedのファンがピッチフォークやトーチで家に押し寄せるほど単純化しすぎるリスクがあるため、Twistedは、任意の(単一の)プロセス内でイベント駆動型の協調マルチタスクを提供します。
これがどのように可能かを理解するには、select()
(select()またはpoll()または同様のOSシステムコールを中心に構築できる)の機能について読む必要があります。基本的には、ファイル記述子のリストでのアクティビティまたはタイムアウトが発生するまで、OSがスリープするように要求する機能によって、すべて駆動されます。
これらの各呼び出しからの目覚めselect()
はイベントです---いくつかのソケットまたはファイル記述子で利用可能な(読み取り可能)入力を含むもの、または他の(書き込み可能な)記述子またはソケットで利用可能になるバッファリングスペース、いくつかの例外条件(TCPアウトオブバンドPUSHされたパケットなど)、またはTIMEOUT。
したがって、Twistedプログラミングモデルは、これらのイベントの処理を中心に構築され、結果の「メイン」ハンドラーでループし、ハンドラーにイベントをディスパッチできるようにします。
個人的には、Twistedという名前をプログラミングモデルを思い起こさせるものだと思います。問題へのアプローチは、ある意味で「ねじれ」ている必要があるためです。プログラムを入力データと出力または結果に対する一連の操作として考えるのではなく、プログラムをサービスまたはデーモンとして記述し、さまざまなイベントへの反応を定義します。(実際、Twistedプログラムのコアとなる「メインループ」は(通常は?常に?)aですreactor()
)。
Twistedを使用する上での主な課題は、イベント駆動モデルに心をゆがめ、Twistedフレームワーク内で連携するように作成されていないクラスライブラリやツールキットの使用を避けることです。Twistedが、SSHプロトコル処理、curses、および独自のサブプロセス/ Popen関数用の独自のモジュール、および最初は赤面したように、Python標準ライブラリの内容を複製しているように見える他の多くのモジュールおよびプロトコルハンドラーを提供するのはこのためです。
Twistedを使用するつもりがない場合でも、概念的なレベルで理解することは有用だと思います。スレッド化、マルチプロセッシング、さらにはサブプロセス処理、さらにはあなたが着手する分散処理におけるパフォーマンス、競合、イベント処理についての洞察を与えるかもしれません。
(注: Python 3.xの新しいバージョンには、async def、@ async.coroutineデコレーター、awaitキーワードなどのasyncio(非同期I / O)機能が含まれており、将来のサポートから得られます。これらはすべておおまかに似ていますプロセス(協調マルチタスク)の観点からねじれた)。(Python 3のTwistedサポートの現在のステータスについては、https://twistedmatrix.com/documents/current/core/howto/python3.htmlを確認してください)
分散オプション:
まだ尋ねていないが、検討する価値のある処理のもう1つの領域は、分散処理の領域です。分散処理と並列計算のための多くのPythonツールとフレームワークがあります。個人的には、最も簡単に使用できるのは、そのスペースにあるとはあまり考えられないものだと思います。
Redisの周りに分散処理を構築するのはほとんど簡単です。キーストア全体を使用して、作業単位と結果を保存できます。RedisLISTをQueue()
同様のオブジェクトとして使用でき、PUB / SUBサポートをと同様のEvent
処理に使用できます。キーをハッシュして値を使用し、Redisインスタンスの緩いクラスター全体に複製して、トポロジーとハッシュトークンマッピングを保存して、ワーカーを調整するための単一インスタンスの容量を超えてスケーリングするための一貫したハッシュとフェイルオーバーを提供できます。それらの間でデータ(ピクル化、JSON、BSON、またはYAML)をマーシャリングします。
もちろん、あなたが再実装し、すでに、使用して解決されている機能の多くはRedisの周りに大規模かつより洗練されたソリューションを構築するために開始するようセロリ、ApacheのスパークとHadoopの、飼育係が、etcd、カサンドラのように。これらはすべて、Pythonがサービスにアクセスするためのモジュールを備えています。
[更新:分散システム全体で計算集中型のPythonを検討している場合に考慮すべきいくつかのリソース:IPython ParallelとPySpark。これらは汎用の分散コンピューティングシステムですが、特にアクセスしやすく、人気のあるサブシステムのデータサイエンスとアナリティクスです]。
結論
シングルスレッドから、サブプロセスへの単純な同期呼び出し、ポーリングされたサブプロセスのプール、スレッド化およびマルチプロセッシング、イベント駆動型の協調マルチタスク、そして分散処理に至るまで、Pythonのさまざまな処理選択肢があります。