为什么get_event_loop不能与run_in_executor一起使用

时间:2020-03-16 10:55:44

标签: python python-3.x python-asyncio

谁能说出下面的代码为什么

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1

在下面得到错误:

import asyncio
import time
from concurrent.futures import ThreadPoolExecutor

ASYNC_INTERVAL = 0.1

def plain_hello_world(name):
    s = "Hello world "+str(name)
    print(s)
    return s

def plain_loop(name, t):
    start_time = time.time()
    prev_time = start_time
    while (time.time() - start_time < t):
        if time.time() - prev_time > ASYNC_INTERVAL:
            prev_time = time.time()
            plain_hello_world(name)

def task1():
    loop = asyncio.get_event_loop()
    task = loop.run_in_executor(None, plain_loop, "func", 1)
    loop.run_until_complete(task)

def task2():
    loop = asyncio.get_event_loop()
    task = loop.run_in_executor(None, task1)
    loop.run_until_complete(task)

if __name__ == "__main__":
    task2()

问题:

我不明白为什么会发生这种错误。

仅运行Traceback (most recent call last): File "asyncio_practice4.py", line 28, in <module> task2() File "asyncio_practice4.py", line 25, in task2 loop.run_until_complete(task) File "/usr/lib/python3.6/asyncio/base_events.py", line 484, in run_until_complete return future.result() File "/usr/lib/python3.6/concurrent/futures/thread.py", line 56, in run result = self.fn(*self.args, **self.kwargs) File "asyncio_practice4.py", line 18, in task1 loop = asyncio.get_event_loop() File "/usr/lib/python3.6/asyncio/events.py", line 694, in get_event_loop return get_event_loop_policy().get_event_loop() File "/usr/lib/python3.6/asyncio/events.py", line 602, in get_event_loop % threading.current_thread().name) RuntimeError: There is no current event loop in thread 'ThreadPoolExecutor-0_0'. 很好,但是运行task1()却说没有当前的evet循环。 (但是我认为应该,我没有创建新线程)

有人知道发生了什么事吗?

假设我们只能在run_in_executor()上工作,该如何解决?

注意:

调用2 task2()的原因是因为上面的代码模仿了将第3个lib集成到异步代码中。

run_in_executor()plain_hello_world()plain_loop()是lib中的代码,我无法修改。

假设task1()运行100秒钟,而我不想等待它,因此我尝试在执行程序中运行它,就像其他普通函数如何与asyncio一起工作。

编辑: 根据答案,这里是有效的修订版本:

task1()

尽管我不确定它的“正确”或良好程度。

1 个答案:

答案 0 :(得分:1)

我不明白为什么会发生这种错误。

之所以发生,是因为task1假定它将在主线程(get_event_loop()按需创建事件循环)或先前调用set_event_loop的线程中运行设置事件循环。由于run_in_executor在除主线程之外的其他线程中调用其函数,并且您的代码在调用set_event_loop()之前没有调用,因此会出现错误。

假设task1()运行100s,而我不想等待它,所以我尝试在执行程序中运行它,就像其他普通函数如何与asyncio一起工作。

运行同步功能而不等待它不是asyncio要做的事情,这是常规线程的工作。例如:

def task1_bg():
    def work():
        asyncio.set_event_loop(asyncio.new_event_loop())
        task1()
    threading.Thread(target=work).start()

if __name__ == '__main__':
    task1_bg()
    # do something else...