asyncico多合併タスクはtoo many file descriptors in selectの解決構想を誤報します。
3856 ワード
問題の説明:
s 3プログラムはtonado web人顔検出機能をテストするテスト関数です。コンカレントにいますreaquestの写真の数が大きいとエラーが発生します。
コードから見て、非同期方法mainでは、concurrent_requestsはリストジェネレータで、中の各オブジェクトは一回tonadoのサービスコールで結果を返します。リスト生成器は関数asyncico.gatherによって呼び出され、Awaitableオブジェクトを返します。ここのawaitキーワードは配合関数asyncのキーワードで使われています。自分の協働を保留して、もう一つの協働が終わるまで待つことを示しています。
main関数は協働オブジェクトとして定義されていますが、その呼び出しはすぐに関数を実行することなく、協働オブジェクトに戻ります。協働対象はイベントサイクルに登録する必要があり、イベントサイクルから呼び出します。したがって、コードの最後に
エラーメッセージもイベントサイクルからきています。until_completteの方法
イベントループループに登録されているasync main方法だけが協働taskとして処理されると見られます。コードの中ではmainメソッドを全体的に協働と見なしています。この協働範囲内のコードにはawaitが現れています。つまり、この関数が詰まると、この協働は他の協働を呼び出すために制御権を委譲します。私たちが実現したいのは、main関数の内部で、複数のtonado webクエリに対して、複数のtonadoクエリを異なるプロセスと見なしてもいいです。メールを协途とするのではなく、mainの中でawaitに会ってmainプログラムを挂けます。ここには协调しかないので、これは主要な问题ではなく、美化する部分だけが必要です。
コードの主な問題はasyncico内部でselect方法を使用しています。開くファイルの文字長に対して、select方法は最大の制限があります。一度に多すぎるweb呼び出し関数をタスクとして必要とすると、Listが大きすぎてエラーが発生します。同時進行の思想は間違っていません。ここでコールバックインターフェースを使ったほうがいいです。
考えをまとめる
私たちが望んでいるのは、tonadoに対するサービスの呼び出しが並行して行われており、コールバックインターフェースを使って合併を実現するためのtonadoサービスへのアクセスです。
そこで、まずtonadoへのアクセス関数をサポートコール方式に書きます。
参考文章pythonの重要モジュール-asynic asyncic非同期爬虫類
s 3プログラムはtonado web人顔検出機能をテストするテスト関数です。コンカレントにいますreaquestの写真の数が大きいとエラーが発生します。
async def request_images(images):
async with aiohttp.ClientSession(json_serialize=ujson.dumps) as session:
url = "http://localhost:9999/images"
payload = {'instances': images}
async with session.post(url, json=payload) as resp:
v= await resp.text()
print(v)
async def main():
...
concurrent_requests = (request_images(re_im2) for i in range(10000))
await asyncio.gather(*concurrent_requests)
...
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
エラーメッセージ:Traceback (most recent call last):
File "C:/Users/14192/MTCNN-zzk/MTCNN/s3aiosend_test.py", line 58, in
loop.run_until_complete(main())
File "C:\Users\14192\Anaconda3\lib\asyncio\base_events.py", line 454, in run_until_complete
self.run_forever()
File "C:\Users\14192\Anaconda3\lib\asyncio\base_events.py", line 421, in run_forever
self._run_once()
File "C:\Users\14192\Anaconda3\lib\asyncio\base_events.py", line 1389, in _run_once
event_list = self._selector.select(timeout)
File "C:\Users\14192\Anaconda3\lib\selectors.py", line 323, in select
r, w, _ = self._select(self._readers, self._writers, [], timeout)
File "C:\Users\14192\Anaconda3\lib\selectors.py", line 314, in _select
r, w, x = select.select(r, w, w, timeout)
ValueError: too many file descriptors in select()
コード解析コードから見て、非同期方法mainでは、concurrent_requestsはリストジェネレータで、中の各オブジェクトは一回tonadoのサービスコールで結果を返します。リスト生成器は関数asyncico.gatherによって呼び出され、Awaitableオブジェクトを返します。ここのawaitキーワードは配合関数asyncのキーワードで使われています。自分の協働を保留して、もう一つの協働が終わるまで待つことを示しています。
main関数は協働オブジェクトとして定義されていますが、その呼び出しはすぐに関数を実行することなく、協働オブジェクトに戻ります。協働対象はイベントサイクルに登録する必要があり、イベントサイクルから呼び出します。したがって、コードの最後に
loop = asyncio.get_event_loop() loop.run_until_complete(main())
という2行のコードを使用して、イベントサイクルを開始し、イベントサイクルにmain関数という協働を登録し、イベントサイクルを開始する。エラーメッセージもイベントサイクルからきています。until_completteの方法
イベントループループに登録されているasync main方法だけが協働taskとして処理されると見られます。コードの中ではmainメソッドを全体的に協働と見なしています。この協働範囲内のコードにはawaitが現れています。つまり、この関数が詰まると、この協働は他の協働を呼び出すために制御権を委譲します。私たちが実現したいのは、main関数の内部で、複数のtonado webクエリに対して、複数のtonadoクエリを異なるプロセスと見なしてもいいです。メールを协途とするのではなく、mainの中でawaitに会ってmainプログラムを挂けます。ここには协调しかないので、これは主要な问题ではなく、美化する部分だけが必要です。
コードの主な問題はasyncico内部でselect方法を使用しています。開くファイルの文字長に対して、select方法は最大の制限があります。一度に多すぎるweb呼び出し関数をタスクとして必要とすると、Listが大きすぎてエラーが発生します。同時進行の思想は間違っていません。ここでコールバックインターフェースを使ったほうがいいです。
考えをまとめる
私たちが望んでいるのは、tonadoに対するサービスの呼び出しが並行して行われており、コールバックインターフェースを使って合併を実現するためのtonadoサービスへのアクセスです。
そこで、まずtonadoへのアクセス関数をサポートコール方式に書きます。
async def request_images(images):
async with aiohttp.ClientSession(json_serialize=ujson.dumps) as session:
url = "http://localhost:9999/images"
payload = {'instances': images}
async with session.post(url, json=payload) as resp:
return await resp.text()
def post_deal(content):
print(content)
loopイベントをmain関数にループし、訪問ごとにtonadoサービスへの非同期呼び出しを実現します。def main():
face_img = cv2.imread(im_name)
re_im = face_img
re_im2 = load_image(im_name)
import time
start = time.time()
loop = asyncio.get_event_loop()
# concurrent_requests = [asyncio.ensure_future(request_images(re_im2)) for i in range(10000)]
for i in range(10000):
concurrent_request = asyncio.ensure_future(request_images(re_im2))
concurrent_request.add_done_callback(post_deal)
loop.run_until_complete(concurrent_request)
end = time.time() - start
print(end)
if __name__ == '__main__':
main()
このようにコードの問題は非同期フィードバックによって解決されました。参考文章pythonの重要モジュール-asynic asyncic非同期爬虫類