背景: 在使用了asyncio的情况下又想使用多线程
参考: https://gist.github.com/lars-tiede/01e5f5a551f29a5f300e
code:
# refer to https://gist.github.com/lars-tiede/01e5f5a551f29a5f300e
import asyncio
import random
from concurrent.futures import ThreadPoolExecutor, as_completed
def thr(i):
# we need to create a new loop for the thread, and set it as the 'default'
# loop that will be returned by calls to asyncio.get_event_loop() from this
# thread.
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
ret = loop.run_until_complete(do_stuff(i))
loop.close()
return ret
async def do_stuff(i):
ran = random.uniform(0.1, 0.5)
await asyncio.sleep(ran) # NOTE if we hadn't called
# asyncio.set_event_loop() earlier, we would have to pass an event
# loop to this function explicitly.
print(i, ran)
return ran
def main():
num_threads = 10
with ThreadPoolExecutor(num_threads) as executor:
futures = {}
for i in range(num_threads):
future = executor.submit(thr, i)
futures[future] = i
for future in as_completed(futures):
ret = future.result()
print(ret, futures[future])
if __name__ == "__main__":
main()
但是,上面的代码在和某些aio库配合使用时会block,原因未知
aio官方推荐的并发方法上略微改进后如下。
import asyncio
import random
import time
async def do_stuff(i):
ran = random.uniform(1, 5)
await asyncio.sleep(ran) # NOTE if we hadn't called
# asyncio.set_event_loop() earlier, we would have to pass an event
# loop to this function explicitly.
print(i, time.time(), ran)
return ran
async def main():
now = time.time()
futures = [do_stuff(i) for i in range(10000)]
await asyncio.gather(
*futures
)
print(time.time() - now)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())