如何解决api请求的初学者异步/等待问题 结果
我想加快一些API请求...为此,我试图找出方法并复制一些正在运行的代码,但是当我尝试自己的代码时,它不再是异步的。也许有人发现失败了?
复制代码(来自stackoverflow的猜测):
#!/usr/bin/env python3
import asyncio
@asyncio.coroutine
def func_normal():
print('A')
yield from asyncio.sleep(5)
print('B')
return 'saad'
@asyncio.coroutine
def func_infinite():
for i in range(10):
print("--%d" % i)
return 'saad2'
loop = asyncio.get_event_loop()
tasks = func_normal(),func_infinite()
a,b = loop.run_until_complete(asyncio.gather(*tasks))
print("func_normal()={a},func_infinite()={b}".format(**vars()))
loop.close()
我的“自己的”代码(我最后需要返回一个列表并合并所有函数的结果):
import asyncio
import time
@asyncio.coroutine
def say_after(start,count,say,yep=True):
retl = []
if yep:
time.sleep(5)
for x in range(start,count):
retl.append(x)
print(say)
return retl
def main():
print(f"started at {time.strftime('%X')}")
loop = asyncio.get_event_loop()
tasks = say_after(10,20,"a"),say_after(20,30,"b",False)
a,b = loop.run_until_complete(asyncio.gather(*tasks))
print("func_normal()={a},func_infinite()={b}".format(**vars()))
loop.close()
c = a + b
#print(c)
print(f"finished at {time.strftime('%X')}")
main()
还是我完全错了,应该使用多线程解决该问题吗?对于API请求返回需要合并的列表的最佳方法是什么?
解决方法
为每个需要改进的部分添加了注释。删除了一些代码即可。
事实上,使用协程包装的range()
和使用async def
并没有发现任何性能提升的可能,而繁重的操作可能值得。
import asyncio
import time
# @asyncio.coroutine IS DEPRECATED since python 3.8
@asyncio.coroutine
def say_after(wait=True):
result = []
if wait:
print("I'm sleeping!")
time.sleep(5)
print("'morning!")
# This BLOCKs thread,but release GIL so other thread can run.
# But asyncio runs in ONE thread,so this still harms simultaneity.
# normal for is BLOCKING operation.
for i in range(5):
result.append(i)
print(i,end='')
print()
return result
def main():
start = time.time()
# Loop argument will be DEPRECATED from python 3.10
# Make main() as coroutine,then use asyncio.run(main()).
# It will be in asyncio Event loop,without explicitly passing Loop.
loop = asyncio.get_event_loop()
tasks = say_after(),say_after(False)
# As we will use asyncio.run(main()) from now on,this should be await-ed.
a,b = loop.run_until_complete(asyncio.gather(*tasks))
print(f"Took {time.time() - start:5f}")
loop.close()
main()
更好的方式:
import asyncio
import time
async def say_after(wait=True):
result = []
if wait:
print("I'm sleeping!")
await asyncio.sleep(2) # 'await' a coroutine version of it instead.
print("'morning!")
# wrap iterator in generator - or coroutine
async def asynchronous_range(end):
for _i in range(end):
yield _i
# use it with async for
async for i in asynchronous_range(5):
result.append(i)
print(i,end='')
print()
return result
async def main():
start = time.time()
tasks = say_after(),say_after(False)
a,b = await asyncio.gather(*tasks)
print(f"Took {time.time() - start:5f}")
asyncio.run(main())
结果
您的代码:
DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8,use "async def" instead
def say_after(wait=True):
I'm sleeping!
'morning!
01234
01234
Took 5.003802
更好的异步代码:
I'm sleeping!
01234
'morning!
01234
Took 2.013863
请注意,固定代码现在可以在其他任务处于休眠状态时完成其工作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。