2

python | 多线程中的 event loop

 1 year ago
source link: https://benpaodewoniu.github.io/2022/09/12/python166/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

python | 多线程中的 event loop

2022-09-12python进阶异步编程基础

21

这篇文章算是

import asyncio
import traceback
from concurrent.futures import ThreadPoolExecutor, as_completed

import aiohttp


class T:

async def get(self, index):
async with aiohttp.ClientSession() as session:
for j in range(10):
async with session.get("http://www.baidu.com") as r:
t = await r.text()
print(index)


test = T()


def main(index):
asyncio.run(test.get(index))


if __name__ == '__main__':
task_list = []
pools = ThreadPoolExecutor(5)
for i in range(5):
task_list.append(pools.submit(main, i))

# 阻塞主进程
for result in as_completed(task_list):
data = result.result()

print("end")

上面的代码运行是没有问题的。

import asyncio
import traceback
from concurrent.futures import ThreadPoolExecutor, as_completed

import aiohttp


class T:

async def get(self, index):
async with aiohttp.ClientSession() as session:
for j in range(10):
async with session.get("http://www.baidu.com") as r:
t = await r.text()
print(index)


test = T()


def main(index):
loop = asyncio.get_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(test.get(index))


if __name__ == '__main__':
task_list = []
pools = ThreadPoolExecutor(5)
for i in range(5):
task_list.append(pools.submit(main, i))

# 阻塞主进程
for result in as_completed(task_list):
data = result.result()

print("end")
RuntimeError: There is no current event loop in thread 'ThreadPoolExecutor-0_0'.

这是因为,主线程可以通过 get_event_loop 获得一个 event loop,但是,多线程是不行的,需要明面申请。

所以,可以改成

import asyncio
import traceback
from concurrent.futures import ThreadPoolExecutor, as_completed

import aiohttp


class T:

async def get(self, index):
async with aiohttp.ClientSession() as session:
for j in range(10):
async with session.get("http://www.baidu.com") as r:
t = await r.text()
print(index)


test = T()


def main(index):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(test.get(index))


if __name__ == '__main__':
task_list = []
pools = ThreadPoolExecutor(5)
for i in range(5):
task_list.append(pools.submit(main, i))

# 阻塞主进程
for result in as_completed(task_list):
data = result.result()

print("end")

上面 3 个例子清晰的表明了如何在多线程中使用协程。

有的人认为这不是脱裤子放屁,多此一举吗?直接一个协程不就行了吗,而且,多线程还有切换的开销,这样做不是降低速度吗?

在多线程中用协程,是和使用场景有关系的,不过在这里不再展开。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK