Python异步IO,可以等待/产生整个myFunction()
我已经编写了一个对象库,其中许多对象进行HTTP/IO调用。由于安装开销,我一直在考虑转移到asyncio,但我不想重写底层代码 我一直希望将asyncio包装在我的代码中,以便异步执行函数,而不必用wait/yield替换我所有的深层/底层代码 我首先尝试了以下几点:Python异步IO,可以等待/产生整个myFunction(),python,asynchronous,python-3.5,python-asyncio,Python,Asynchronous,Python 3.5,Python Asyncio,我已经编写了一个对象库,其中许多对象进行HTTP/IO调用。由于安装开销,我一直在考虑转移到asyncio,但我不想重写底层代码 我一直希望将asyncio包装在我的代码中,以便异步执行函数,而不必用wait/yield替换我所有的深层/底层代码 我首先尝试了以下几点: async def my_function1(some_object, some_params): #Lots of existing code which uses existing objects #
async def my_function1(some_object, some_params):
#Lots of existing code which uses existing objects
#No await statements
return output_data
async def my_function2():
#Does more stuff
while True:
loop = asyncio.get_event_loop()
tasks = my_function(some_object, some_params), my_function2()
output_data = loop.run_until_complete(asyncio.gather(*tasks))
print(output_data)
我很快意识到,虽然这段代码在运行,但实际上没有任何事情是异步发生的,函数是同步完成的。我对异步编程非常陌生,但我认为这是因为我的两个函数都没有使用关键字wait或yield,因此这些函数不是cootroutines,也不是yield,因此没有机会移动到不同的cootroutine。如果我错了,请纠正我
我的问题是,是否可以将复杂的函数(在函数内部深处进行HTTP/IO调用)封装在asyncio
wait
关键字中,例如
async def my_function():
print("Welcome to my function")
data = await bigSlowFunction()
更新-遵循卡尔森的回答
由于卡尔森公司接受了以下答案,我使用了以下代码,该代码运行良好:
from concurrent.futures import ThreadPoolExecutor
import time
#Some vars
a_var_1 = 0
a_var_2 = 10
pool = ThreadPoolExecutor(3)
future = pool.submit(my_big_function, object, a_var_1, a_var_2)
while not future.done() :
print("Waiting for future...")
time.sleep(0.01)
print("Future done")
print(future.result())
这非常好用,
future.done()
/sleep循环让您知道通过异步可以使用多少CPU周期。简单的回答是,如果不在代码中明确标记控制可以传递回事件循环的点,您就无法获得asyncio
的好处。这是通过将IO繁重的函数转换为协同程序来实现的,就像您假设的那样
在不改变现有代码的情况下,您可能会通过greenlets实现您的目标(看看或)
另一种可能是利用Python的包装功能,将对已经编写的函数的调用传递给一些人,并产生最终的结果。请注意,这是多线程编程的所有警告
类似于
from concurrent.futures import ThreadPoolExecutor
from thinair import big_slow_function
executor = ThreadPoolExecutor(max_workers=5)
async def big_slow_coroutine():
await executor.submit(big_slow_function)
从Python3.9开始,您可以使用
asyncio.to_thread()
将阻塞(非异步)函数包装到协同程序中,使其成为可等待的。表中给出的示例为:
这似乎比使用
concurrent.futures
创建协同程序更像是一种联合方法,但我还没有对它进行过广泛的测试。感谢您的回复,我将看看将低级代码更改为异步是否可行。同时感谢您提出的备选方案,这些方案可能更容易实施。
def blocking_io():
print(f"start blocking_io at {time.strftime('%X')}")
# Note that time.sleep() can be replaced with any blocking
# IO-bound operation, such as file operations.
time.sleep(1)
print(f"blocking_io complete at {time.strftime('%X')}")
async def main():
print(f"started main at {time.strftime('%X')}")
await asyncio.gather(
asyncio.to_thread(blocking_io),
asyncio.sleep(1))
print(f"finished main at {time.strftime('%X')}")
asyncio.run(main())
# Expected output:
#
# started main at 19:50:53
# start blocking_io at 19:50:53
# blocking_io complete at 19:50:54
# finished main at 19:50:54