web-dev-qa-db-ja.com

Asyncio対Gevent

バックグラウンド

私はかつて、多くのカスタムI/Oコードを同期的に記述し、スレッドを使用してスケーリングしたPython2システムで作業しました。ある時点で、それ以上スケーリングできなくなり、非同期プログラミングに切り替える必要があることに気付きました。

  • ツイスト が一般的な選択でしたが、コールバックの地獄を避けたかったのです。
  • @inlineCallbacks デコレータ。他のいくつかのライブラリと同様に、ジェネレータマジックを使用してコルーチンを効果的に実装しました。それはより許容できるものでしたが、少し不安定な感じがしました。
  • そして、 gevent が見つかりました。あなたがしなければならなかったすべては:
from gevent import monkey
monkey.patch_all()

それと同じように、ソケット、データベーストランザクション、すべて純粋なPythonで書かれたすべての標準I/Oは非同期で、グリーンレットを使用してバックグラウンドで生成および切り替えを行いました。

それは完璧ではありませんでした:

  • その当時、それはWindowsではうまく機能しませんでした(そして今日でもいくつかの制限があります)。幸い、私たちはLinuxで実行していました。
  • C拡張機能をサルパッチすることができなかったため、たとえばMySQLdbを使用できませんでした。幸いなことに、PyMySQLのような純粋なPython代替案がたくさんありました。

質問

最近では、Python 3の方がはるかに人気があり、それに伴って asyncio です。個人的には素晴らしいと思いますが、最近、どのような点が違うのかと尋ねられましたgeventを使って実装したもので、十分な答えを出すことができませんでした。

これは主観的に聞こえるかもしれませんが、私は実際に実際のユースケースを探しています。 。これまでに収集した考慮事項は次のとおりです。

  1. 私が言ったように、geventはWindowsではかなり制限されています。繰り返しになりますが、私が知っているほとんどの製品コードはLinuxで実行されます。

    Windowsで実行する必要がある場合は、asyncioを使用します。

  2. GeventはCの拡張機能をサルパッチすることはできません。ただし、asyncioはモンキーパッチanythingを実行できません。

    新しいDBテクノロジーが登場し、それを使用したいが、純粋なPythonライブラリがないため、Geventと統合できない場合があります。ことは、asyncioと統合できるio *ライブラリがないときと同じように行き詰まっていることです!もちろんワーカースレッドとエグゼキューターはありますが、それは重要ではなく、どちらの場合でも同じように機能します。

  3. 個人的な好みの問題だと言う人もいますが、同期プログラミングは本質的に非同期プログラミングよりも簡単だと言って差し支えないと思います(考えてみてください。ソケットを操作できる初心者プログラマーに会ったことがありますが、理解に苦労しています。それらを適切に選択/ポーリングする方法、または先物/約束で考える方法?そして、あなたは逆に会ったことがありますか?).

    とにかく行かないで。この点については頻繁に取り上げられるので対処したかったのですが( here's redditについての議論)、私が実際に求めているのは実用的を使用する理由があるシナリオですどちらか一方。

  4. Asyncioは標準ライブラリの一部です。それは巨大です:それはよく維持され、十分に文書化されていることを意味し、誰もがそれについて知っており、デフォルトでそれを使用します。

    ただし、Geventを使用するために知っておく必要があるGeventの量が少ないこと(および、Geventがかなりよく保守され、文書化されていること)を考慮すると、それほど重要ではないようです。したがって、先物を含む最も複雑なシナリオでもStackOverflowには複数の回答がありますが、先物をまったく使用しない可能性も同様に現実的です。

確かに、GuidoとPythonコミュニティは、Guidoに多大な努力を払い、言語に新しいキーワードを導入することにも十分な理由がありました-私はそれらを見つけることができないようです。

2つの主な違いは何ですか?どのシナリオで明らかになりますか?

25
Dan Gittik

実際の使用法からの「簡単な」答え:

  1. Geventの良いところ—できますpatchこと、つまり[理論的には]同期ライブラリを使用できることを意味します。つまりDjangoにパッチを適用できます。
  2. Geventの悪い点—すべてにパッチを適用できるわけではない必須パッチを適用できないDBドライバーを使用すると、運命にある
  3. Geventについて最悪のこと—それは「魔法」です。 「patch_all」で何が起こるかを理解するために必要な労力は膨大であり、同じ努力が開発チームの新しい人を見つける/採用する場合にも当てはまります。さらに悪いことに、geventベースのコードのデバッグは地獄です。悪くはないとしても、コールバックとほとんど同じです。

後でポイントが重要だと思います。ソフトウェアエンジニアリングで最も過小評価されているのは、コードがreadであることを意図しており、効率的に書き込まれたり実行されたりしないことです(後でそうである場合は、pythonシステムレベルの言語に変換します。Asyncioには、非同期プログラミングの欠落部分がありました— 事前定義および制御コンテキスト切り替えポイント。実際に同期コードを記述しています(つまり、突然のスレッド切り替え、ロックについては考えていません) 、キューなど)、およびawait ...あなたがknowを呼び出したときIOブロッキングなので、CPUの準備ができている他のイベントループをイベントループで選択し、後で現在の状態を取得します。

これがasyncioの優れた点です。保守が簡単です。欠点は、ほとんどすべての「世界」も非同期でなければならないということです— DBドライバー、httpツール、ファイルハンドラー。そして時々あなたはライブラリーを見逃すでしょう、それはほとんど保証されています。

10
Slam