まず、tl;dr:
concurrent.futures
3.2+ を使用futures
している場合は使用し、2.x を使用している場合は同じものをバックポートする PyPI のモジュールを使用します。
a を使用してコードを記述し、ワンライナーの変更として aThreadPoolExecutor
に切り替えることができます。ProcessPoolExecutor
また、API は非常に最小限でシンプルなので、混乱することはありません。
また、ボットを簡単に拡張できるようにしたいので、コマンドが非同期で実行することを要求することはオプションではありません。
それがどのように続くかわかりません。非同期コードについて、拡張性を低下させるものは何もありません。もちろん、それを拡張するには非同期コードの書き方を知らなければなりませんが、何千人もの初心者の JS プログラマーが毎日、ほぼ無難な作業を行っていますmonocle
。.)。また、説明の中でこれらのことを明示的に「コールバック」と呼んでいるという事実は、すでにそれらの用語で考えていることを意味します…</p>
inlineCallbacks
twisted
tulip
これが実際に要件であると確信している場合は、twisted
受け入れられません。しかし、gevent
(andeventlet
など) は、完全に同期しているように見えるコードを記述して、非同期で実行することができます。
次:
これらのコールバックのいくつかを並行して実行するために推奨するモジュールとその理由は何ですか?
それらを並行して実行する必要がありますか (複数のコアを利用して複数の CPU バウンド ジョブを同時に実行できます)、同時に実行する必要がありますか (長時間実行されるジョブは他のジョブをブロックしません)、またはどちらも実行しません (時間がかかる限り)ジョブが完了すると、それらが並列化されているか、インターリーブされているか、シリアル化されているかは関係ありません)?
並列処理が必要な場合は、multiprocessing
. それを回避する方法は本当にありません。GIL を使用すると、1 つのプロセスで複数のコアを使用できなくなります。
同時実行のみが必要な場合は、 または のいずれかを使用できthreading
ますmultiprocessing
。プロセスは、Windows と Unix の間 (場合によっては Unix 間でも) のオーバーヘッドや移植性の問題を意味する可能性があり、データをやり取りする方法、または必要に応じてデータを共有する方法を考えなければならない場合があります。一方、スレッドは、データの受け渡しや共有について考える必要がないため、レースやその他のバグを誤って作成しやすくなります。(トレードオフの詳細については、isedev の優れた回答を参照してください。)
どちらも必要ない場合は、gevent
(または類似のもの)、threading
、またはを使用できますmultiprocessing
。数百のスレッドまたはプロセスを作成するのと同じくらい簡単に、10000 個のグリーン スレッドを作成して切り替えることができ、オーバーヘッドもはるかに少なくなります。ただし、長時間実行される CPU バウンドのコマンドが 1 つあるだけで、システム全体が停止する可能性があります。
どちらを使用する場合でも、グリーンレット、スレッド、またはプロセスのプールを使用して、コマンドをキューから取り出します (コマンドごとに新しいものをスピンオフしたり、より複雑なものを構築したりするのではなく)。
そのmultiprocessing
ようなものが組み込まれていますが、そうでthreading
はありません。(実際には、 にthreading
基づくスレッドプールがありますがmultiprocessing
、 ではなく にありthreading
ます。また、パブリック API の一部ではありません。)
には驚くほどクールなものがたくさんありmultiprocessing
ます。必要な場合は、必ず使用してください。(さらに優れた機能を備えたサードパーティのライブラリもあり、複雑なユースケースをはるかに簡単にしたり、multiprocessing
できないことを実行したりできます。)しかし、そうでない場合futures
は、はるかに単純であり、機能ワンライナーの変更でスレッドとプロセスを使用して同じシステムをテストする(または実行時に簡単に行うことさえできる)ことは非常に素晴らしいことです。