我有一个程序,它以同步的方式在一个无限循环中运行。这个程序需要调用一个外部库中的函数,而这个函数会阻塞代码执行。我怎样才能把这个阻塞函数转换成一个非阻塞形式,以便它能在程序的无限循环中顺畅运行呢?
下面是一个示例代码:
import time
SECONDS_TO_WAIT = 3
# 模拟外部库中的阻塞函数
def get_data():
time.sleep(SECONDS_TO_WAIT)
return "Data received."
def main():
n = 0
while True:
data = get_data()
print(n)
print(data)
n += 1
if __name__ == "__main__":
main()
我希望这个无限循环不要被阻塞,能够持续打印变量n
,并且只有当get_data()
函数完成执行后才打印变量data
。需要注意的是,我们不能修改get_data()
函数,因为它模拟的是一个外部库的函数,我们没有权限或能力去改动它。
为了更准确地描述我的需求和目标,这里是一个更详细的示例代码:
import time
class LibraryWrapper():
SECONDS_TO_WAIT = 3
def __init__(self):
# 初始化库
self.data = None
# 模拟外部库的阻塞函数
def get_data(self):
time.sleep(self.SECONDS_TO_WAIT)
return "Data received."
class Program():
def __init__(self, library_wrapper):
self.library_wrapper = library_wrapper
def run(self, user_input):
# 执行一些操作
print(user_input)
if self.library_wrapper.data:
print(self.library_wrapper.data)
def main():
library_wrapper = LibraryWrapper()
program = Program(library_wrapper)
user_input = 0
while True:
# 模拟非阻塞用户输入
user_input += 1
library_wrapper.data = library_wrapper.get_data()
program.run(user_input)
if __name__ == "__main__":
main()
我猜测解决这个问题的最佳方案可能是使用asyncio
库。我已经阅读了官方文档,对协程、async
和await
关键字、任务和未来有了一定的了解。
我尝试运行了如下代码,希望至少能获得一个实现预期结果的思路,但并没有成功。即使使用了asyncio
库,无限循环依然会被阻塞。
import asyncio
SECONDS_TO_WAIT = 3
async def get_data():
await asyncio.sleep(SECONDS_TO_WAIT)
return "Data received."
async def main():
n = 0
while True:
task = asyncio.create_task(get_data())
print(n)
print(await task)
n += 1
asyncio.run(main())
# 输出类似于:
# 0
# 等待3秒...
# Data received.
# 1
# 等待3秒...
# Data received.
# 2
我也参考了Stack Overflow上的以下问题,但它们没有提供如何将阻塞函数封装为非阻塞函数的具体方法。
请问我应该如何调整代码,使得即便在调用外部库的阻塞函数时,我的主循环也能保持非阻塞状态并继续执行其他任务?