【问题标题】:Asyncio .create_task() not running function passed inAsyncio .create_task() 未运行传入的函数
【发布时间】: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 Truefor 循环内,而在这种情况下,它只是在事件侦听器上调用一次)

【问题讨论】:

  • 你是在 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


【解决方案1】:

我才开始使用 asyncio,但我的猜测是 create_task 没有运行任何东西,你可以试试 run_until_complete 代替

【讨论】:

  • 建议在答案中添加更多详细信息,解释为什么您认为这将解决 OP 的问题。请在How do I write a good answer?查看此链接
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-03
相关资源
最近更新 更多