Python asyncio 启动问题求助

2023-02-09 11:16:32 +08:00
 ohayoo

求助大佬们,本菜鸡非专业程序员,只会点皮毛,偶尔做个小工具都是网上抄代码,东拼西凑,现在遇到一个这样的问题不知道怎么解决,还望大佬们能帮忙看看。

我的异步函数第一种方式启动,可以正常运行,但我现在想要换成第二种启动方式,就会报错 This event loop is already running ,可能有大佬想问,第一种方式可以正常跑就行了,为啥非要作死换成第二种呢?是因为 fastapi 的路由函数是异步的,我需要在路由函数里面调用前面这个 ip 查询的异步函数,所以模拟了这样一段代码前来求助。

想问下要怎么改才能在 aaa 这个异步函数里面启动前面的 main 函数呢?

import aiohttp
import asyncio

iplist = ['1.1.1.1', '2.2.2.2', '3.3.3.3']
result = {}

async def get_ipinfo(ip, domain, sem):
    params = {'ip': ip, 'dns': domain}
    async with sem:
        async with aiohttp.ClientSession() as session:
            async with session.get('http://www.abc.com/', params=params) as resp:
                res = await resp.text()
                #res 结果写入全局变量字典中,代码省略


async def main(domain, sem):
    tasks = [get_ipinfo(ip, domain, sem) for ip in iplist]
    await asyncio.gather(*tasks)


################   启动方式 1  ##############
#上面的异步函数启动方式 1 ,可以正常运行

if __name__ == "__main__":
    sem = asyncio.Semaphore(20)
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(main('www.test.com', sem))
    finally:
        loop.run_until_complete(loop.shutdown_asyncgens())
        loop.close()
    print(result)


####################   启动方式 2  #####################
#上面的异步函数启动方式 2 ,报错
#     raise RuntimeError('This event loop is already running')
# RuntimeError: This event loop is already running
#
# During handling of the above exception, another exception occurred:

async def run(domain):
    sem = asyncio.Semaphore(20)
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(main(domain, sem))
    finally:
        loop.run_until_complete(loop.shutdown_asyncgens())
        loop.close()


async def aaa(domain):
    await run(domain)
    print(result)


asyncio.run(aaa('www.test.com'))

1977 次点击
所在节点    Python
6 条回复
jenlors
2023-02-09 11:27:26 +08:00
第二种方式,run 里面就不用再用 run_until_complete 的方式了,直接 await
karlkor
2023-02-09 11:29:58 +08:00
在 async 函数里面执行 coroutine 可以使用 asyncio.create_task, 也就是说在你的第二个 case 里面用 asyncio.create_task 替换掉 loop.run_until_complete
mylifcc
2023-02-09 11:38:07 +08:00
我两个都能运行
mylifcc
2023-02-09 11:39:33 +08:00
原来是没保存 这网站怎么删评论啊
mylifcc
2023-02-09 11:42:05 +08:00
async def run(domain):
sem = asyncio.Semaphore(20)
await main(domain, sem)
这样就可以了
ohayoo
2023-02-09 12:22:54 +08:00
@jenlors @karlkor @mylifcc 感谢大佬们,两种方式都可以,
官方文档有写,自己眼瞎居然没看到

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/914505

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX