同時実行および戻り結果の比較について(py版)
3726 ワード
前言
py GIL, , .
threading multiprocessing, concurrent.futures asyncio(3.5以降のコモンシップ)gevent(monkey_patchと呼ばれることが多い)
ソースコードについては、興味があり、研究して、やはり収穫があります.日を改めて開編する.asyncioはyield魔改に基づいており、全体の生態はまだ成熟しておらず、ツッコミを入れられることが多いが、私が現在使っている限りでは、悪くない.
monkey_patchは長時間のオンライン検証やコードの侵入性がなく、性能は信頼できる.
同時的な考慮に基づいて、これらはすべて良い考え方です.
义齿
この2つのapiの差は多くなく、異なるといえばmultiprocessingは結果を返すことができ、threadingは結果を返すことができ、一般的に2つの考え方はキューやクラスで1層をカプセル化することである.
Multiprocessingは結果を返します
def req_multi(url:str, result: dict):
r = requests.get(url)
result[url] = r
def main_multi():
process_manager = multiprocessing.Manager()
result_dict = process_manager.dict()
urls = ["http://www.baidu.com", "http://www.zhihu.com"]
reqs = [multiprocessing.Process(target=req_multi, args=(i, result_dict)) for i in urls]
[j.start() for j in reqs]
[j.join() for j in reqs]
print(result_dict)
結果
![image.png](https://upload-images.jianshu.io/upload_images/1500770-b608536e103201be.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
threadingは結果を返す
queueの方式
q = queue.Queue()
def req_threading(url: str):
r = requests.get(url)
q.put({url: r})
def main_threading_queue():
urls = ["http://www.baidu.com", "http://www.zhihu.com"]
results = [threading.Thread(target=req_threading, args=(i,)) for i in urls]
[j.start() for j in results]
[k.join() for k in results]
while q:
print(q.get())
classパッケージ方式
class MainThread(threading.Thread):
def __init__(self, fn_name: str, url: list):
super(MainThread, self).__init__()
self.fn_name = fn_name
self.url = url
self.result = {}
def run(self):
for i in self.url:
r = requests.get(i)
self.result[self.fn_name] = r
非同期方式futures
def main_future():
urls = ["http://www.baidu.com", "http://www.zhihu.com"]
pool = concurrent.futures.ProcessPoolExecutor(max_workers=2)
results = [pool.submit(req_futrue, i) for i in urls]
# results = [pool.map(req_futrue, urls)]
r = [i.result(timeout=10) for i in results]
print(r)
asyncio
import gevent
from gevent import socket
# from gevent import monkey; monkey.patch_all()
import time
start_time = time.time()
async def main_gevnet():
urls = ["http://www.baidu.com", "http://www.baidu.com"]
# jobs_1 = [gevent.spawn(req_1, i )for i in urls]
# jobs_2 = [gevent.spawn(req_2, i )for i in urls]
# for j in jobs_1:
# j.start()
# j.join()
# for k in jobs_2:
# k.start()
# k.join()
job_1 = req_1("http://www.baidu.com")
job_2 = req_2("http://www.baidu.com")
import asyncio
for i in range(100):
loop = asyncio.get_event_loop()
loop.run_until_complete(main_gevnet())
print(time.time() - start_time)
gevent
import gevent
from gevent import socket
# from gevent import monkey; monkey.patch_all()
import time
start_time = time.time()
async def main_gevnet():
urls = ["http://www.baidu.com", "http://www.baidu.com"]
jobs_1 = [gevent.spawn(req_1, i )for i in urls]
jobs_2 = [gevent.spawn(req_2, i )for i in urls]
for j in jobs_1:
j.start()
j.join()
for k in jobs_2:
k.start()
k.join()
# job_1 = req_1("http://www.baidu.com")
# job_2 = req_2("http://www.baidu.com")