この記事では主に、future を通じて同時実行の問題を処理するための Python を紹介します。これは非常に優れており、必要な友人は参考にしてください。 futureの予備理解:
例1: 通常のループメソッド
import os import time import sys import requests POP20_CC = ( "CN IN US ID BR PK NG BD RU JP MX PH VN ET EG DE IR TR CD FR" ).split() BASE_URL = 'http://flupy.org/data/flags' DEST_DIR = 'downloads/' def save_flag(img,filename): path = os.path.join(DEST_DIR,filename) with open(path,'wb') as fp: fp.write(img) def get_flag(cc): url = "{}/{cc}/{cc}.gif".format(BASE_URL,cc=cc.lower()) resp = requests.get(url) return resp.content def show(text): print(text,end=" ") sys.stdout.flush() def download_many(cc_list): for cc in sorted(cc_list): image = get_flag(cc) show(cc) save_flag(image,cc.lower()+".gif") return len(cc_list) def main(download_many): t0 = time.time() count = download_many(POP20_CC) elapsed = time.time()-t0 msg = "\n{} flags downloaded in {:.2f}s" print(msg.format(count,elapsed)) if __name__ == '__main__': main(download_many)
from concurrent import futures from flags import save_flag, get_flag, show, main MAX_WORKERS = 20 def download_one(cc): image = get_flag(cc) show(cc) save_flag(image, cc.lower()+".gif") return cc def download_many(cc_list): workers = min(MAX_WORKERS,len(cc_list)) with futures.ThreadPoolExecutor(workers) as executor: res = executor.map(download_one, sorted(cc_list)) return len(list(res)) if __name__ == '__main__': main(download_many)
future
future は、concurrent.futures モジュールと asyncio モジュールの重要なコンポーネントです
python3.4 以降、標準ライブラリには Future という名前のクラスが 2 つあります: concurrent.futures.Future Futureこれら 2 つのクラスは同じ目的を果たします。両方の Future クラスのインスタンスは、完了する場合と完了しない場合がある遅延計算を表します。 Twisted の Deferred クラスと Tornado フレームワークの Future クラスに似ています 注: 通常、Future は自分で作成するべきではなく、並行フレームワーク (concurrent.futures または asyncio) によってインスタンス化されるべきです
理由: Future は終わりを表します。何かが起こるかどうかを判断する唯一の方法は、実行時間がスケジュールされているため、 concurrent.futures.Future インスタンスは、何かが concurrent.futures.Executor サブクラスに渡されたときにのみ作成されます。
future
クライアント コードは将来の状態を変更できません。同時実行フレームワークは、future によって表される遅延計算が終了した後に future オブジェクトの状態を変更します。計算がいつ終了するかを制御することはできません。
asyncio.Future.result メソッドはタイムアウトの設定をサポートしていません。将来の結果を取得するには、構造体からのyieldを使用するのが最善ですが、concurrent.futures.Future ではこれができません
asyncio であっても concurrent.futures であっても。 .Future では、いくつかの関数が future を返し、他の関数は future を使用します。最初の例では、戻り値はイテレータの __next__ メソッドで呼び出されます。 Future.as_completed 関数の使用に関して、ここでは 2 つのループを使用します。1 つは将来の作成とスケジュールに使用され、もう 1 つは結果
from concurrent import futures from flags import save_flag, get_flag, show, main MAX_WORKERS = 20 def download_one(cc): image = get_flag(cc) show(cc) save_flag(image, cc.lower()+".gif") return cc def download_many(cc_list): cc_list = cc_list[:5] with futures.ThreadPoolExecutor(max_workers=3) as executor: to_do = [] for cc in sorted(cc_list): future = executor.submit(download_one,cc) to_do.append(future) msg = "Secheduled for {}:{}" print(msg.format(cc,future)) results = [] for future in futures.as_completed(to_do): res = future.result() msg = "{}result:{!r}" print(msg.format(future,res)) results.append(res) return len(results) if __name__ == '__main__': main(download_many)
結果は次のとおりです:
concurrent.futures ProcessPoolExecutorクラスは作業を複数のPythonプロセスに分散するため、CPUを集中的に使用する処理を行う必要がある場合は、このモジュールを使用してGILをバイパスし、すべてのCPUコア。
その原理は、ProcessPoolExecutor が N 個の独立した Python インタープリターを作成することです。ここで、N はシステムで利用可能な CPU コアの数です。
使用方法はThreadPoolExecutorメソッドと同じです
以上がPython がフューチャーを通じて同時実行の問題を処理する方法の詳細な例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。