【发布时间】:2021-09-24 23:41:26
【问题描述】:
我正在尝试制作一个在 python 中执行几个与计时器相关的事情的程序,我需要制作它,以便 Asyncio 通过使用 asyncio.get_event_loop().create_task(timer_function(my_parameters)) 调用另一个函数来创建一个任务(无需等待它),我用过这之前在另一个项目中,它工作得很好,但是,在这种情况下,它最终没有像它应该的那样调用timer_function(),我怀疑它发生是因为它在循环内部或与项目结构相关的东西。我现在找不到任何可以工作的东西,只使用await 设法调用该函数,但最终没有使它并行运行。项目结构如下:
async def timer_function(my_parameters):
print('Timer_Function called')
# Do stuff with the parameters
asyncio.sleep(time_based_on_those_parameters)
# Finish doing some other things
# Note: final() doesn't need to be async, I only made it so
# to try and test some fixes
async def final(parameters):
# Do stuff
while True: # This part loops forever every minute
# Do stuff
for i in range(my_range):
if some_condition_a:
asyncio.get_event_loop().create_task(timer_function(my_parameters))
print('Condition A met')
if some_condition_b:
asyncio.get_event_loop().create_task(timer_function(some_different_parameters)
print('Condition B met')
# Do some other stuff
sleep(60)
运行代码后,满足这些条件时打印的所有内容都是
>>> Condition met
但我期望看到的是两者
>>> Condition met
>>> Timer function called
然后我将 await 放在 create_task 部分之前,当时打印的所有内容都是
>>> Timer function called
然后只有当计时器用完并做它需要做的事情是当>>> Condition met
被打印出来。有没有办法改变这种结构以适应 Asyncio 或其他我可以尝试的方法?
编辑:我找到了使用threading 而不是asyncio 的解决方法。代码现在是这样的:
def timer_function(my_parameters): # Sync method now
print('Timer_Function called')
# Do stuff with the parameters
sleep(time_based_on_those_parameters) # No longer asyncio.sleep()
# Finish doing some other things
def final(parameters):
# Do stuff
threads = []
while True: # This part loops forever every minute
# Do stuff
for i in range(my_range):
if some_condition_a:
t = threading.Thread(target=timer_function, args=(my_parameters))
threads.append(t)
t.start()
print('Condition A met')
if some_condition_b:
t = threading.Thread(target=timer_function, args=(my_parameters))
threads.append(t)
t.start()
print('Condition B met')
# Do some other stuff
sleep(60)
这现在按预期工作,所以对我来说我不再需要解决这个问题,但是如果有人知道为什么 Asyncio 在这个结构中不这样做,请告诉我,因为有人可能在未来。 (我检查了我制作的另一个项目
asyncio.get_event_loop().create_task(timer_function(my_parameters))
可以在不等待的情况下调用,不同之处在于在这种情况下它位于 while True 和 for 循环内,而在这种情况下,它只是在事件侦听器上调用一次)
【问题讨论】:
-
你是在 Jupiter notebook 中测试它吗?还是 .py 文件?,因为 Jupiter 运行它们的异步循环,可能会丢失你的输出。
-
@Cristian Contrera 这是一个 .py 文件
-
asyncio.sleep()必须等待,所以它应该是await asyncio.sleep(time_based_on_those_parameters)。另外,sleep(60)看起来不对,也许它也应该是await asyncio.sleep(60)? (目前它在循环之外,不确定这是否是有意的。)请注意,您创建的任务只有在您等待某些东西时才会开始执行,从而将控制权交还给事件循环,而您的while循环似乎没有这样做. -
asyncio.get_event_loop().create_task(timer_function(my_parameters))只是创建任务但不执行,因此您需要等待或附加所有任务并在之后等待。执行发生在线程中,因为您在此处放置了t.start()检查:docs.python.org/3/library/… -
@tard 是的,使用
await运行该方法但停止了其他所有操作(因为它等待他们完成所有操作然后再继续),我认为最好在他们打开和关闭方法时使用线程同时继续循环
标签: python python-asyncio