マルチプロセッシングのプールを使用してプロセスのグループを実行しようとしています。各プロセスは、グリーンレットのgeventプールを実行します。これは、ネットワークアクティビティが多いだけでなく、CPUアクティビティも多いため、帯域幅とすべてのCPUコアを最大化するには、複数のプロセスとgeventの非同期モンキーパッチが必要です。マルチプロセッシングのマネージャーを使用して、データを処理するためにプロセスがアクセスするキューを作成しています。
コードの簡略化されたフラグメントは次のとおりです。
import multiprocessing
from gevent import monkey
monkey.patch_all(thread=False)
manager = multiprocessing.Manager()
q = manager.Queue()
これが生成する例外です:
Traceback (most recent call last):
File "multimonkeytest.py", line 7, in <module>
q = manager.Queue()
File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/managers.py", line 667, in temp
token, exp = self._create(typeid, *args, **kwds)
File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/managers.py", line 565, in _create
conn = self._Client(self._address, authkey=self._authkey)
File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/connection.py", line 175, in Client
answer_challenge(c, authkey)
File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/connection.py", line 409, in answer_challenge
message = connection.recv_bytes(256) # reject large message
IOError: [Errno 35] Resource temporarily unavailable
これは、通常のソケットモジュールとgeventのソケットモジュールの動作の違いによるものだと思います。
サブプロセス内でモンキーパッチを適用すると、キューは正常に作成されますが、サブプロセスがキューからget()を取得しようとすると、非常によく似た例外が発生します。サブプロセスで多数のネットワーク要求を実行するため、ソケットにモンキーパッチを適用する必要があります。
私のバージョンのgeventは、最新のものだと思います。
>>> gevent.version_info
(1, 0, 0, 'alpha', 3)
何か案は?
monkey.patch_all(thread=False, socket=False)
を使用する
私は同様の状況で同じ問題に遭遇し、これをpatch_socket()
関数の下の_gevent/monkey.py
_の115行目まで追跡しました:__socket.socket = socket.socket
_。この行をコメントアウトすると、破損を防ぐことができます。
これは、geventがstdlib socket
ライブラリを独自のものに置き換える場所です。 _multiprocessing.connection
_はsocket
ライブラリを非常に広範囲に使用しており、明らかにこの変更に寛容ではありません。
具体的には、インポートしたモジュールが_socket=False
_を設定せずにgevent.monkey.patch_all()
呼び出しを実行するシナリオでこれが発生します。私の場合、これを行ったのはgrequests
であり、このエラーを修正するには、ソケットモジュールのパッチをオーバーライドする必要がありました。
Geventのコンテキストでマルチプロセッシングを適用すると、残念ながら問題が発生することが知られています。ただし、あなたの論理的根拠は合理的です(「多くのネットワークアクティビティだけでなく、多くのCPUアクティビティ」)。よろしければ、 http://gehrcke.de/gipc をご覧ください。これは主にユースケース向けに設計されています。 gipcを使用すると、完全にgeventを認識する子プロセスをいくつか簡単に生成し、パイプを介して相互に、および/または親と協調的に通信させることができます。
ご不明な点がございましたら、お気軽にお問い合わせください。
元のキューを使用する場合、コードはモンキーパッチを適用したソケットでも正常に機能します。
import multiprocessing
from gevent import monkey
monkey.patch_all(thread=False)
q= multiprocessing.Queue()
交換用のNoseMultiprocessプラグインを作成しました。これは、あらゆる種類のクレイジーなGeventベースのパッチでうまく機能するはずです。
https://pypi.python.org/pypi/nose-gevented-multiprocess/
https://github.com/dvdotsenko/nose_gevent_multiprocess
multiprocess.fork
からプレーンsubprocess.popen
に切り替えます(モジュールレベルの誤って共有されたオブジェクトの問題を修正します)提供されたコードは、Windows7で機能します。
編集:
Ubuntu 11.10 VPSでコードを試したところ、同じエラーが発生したため、以前の回答を削除しました。
のように見えます イベントレットにもこの問題があります