开发者社区> 问答> 正文

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

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

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(\*elf.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()可以,但是与另一run_in_executor()一起运行时,它表示当前没有evet循环。(但是我认为应该,我没有创建新线程)

有人知道发生了什么吗?

以及假设我们只能在task2()上工作,如何解决?

注意:

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

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

Assuming task1() runs for 100s and I do not want to wait for it, so I try to run it in executor as how other plain functions work with asyncio.

Edit: Based on the answer, here is the revision that works:

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

Though I am not sure how "correct" or good it is.

问题来源: stackoverflow

展开
收起
is大龙 2020-03-23 17:38:41 1803 0
1 条回答
写回答
取消 提交回答
  • I do not understand why such error occurs.

    It occurs because task1 assumes that it will run in either the main thread (where get_event_loop() creates an event loop on-demand) or in a thread where set_event_loop was previously called to set up an event loop. Since run_in_executor invokes its function in a thread other than the main thread, and your code doesn't call set_event_loop() before invoking it, you get the error.

    假设task1()运行100s,而我不想等待它,那么我尝试在executor中运行它,因为其他普通函数如何与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...
    

    回答来源:stackoverflow

    2020-03-23 17:38:47
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
SPEED MATTERS:HOW TO PROCESS B 立即下载
Spark SQL: Past, Present and Future 立即下载
Spark SQL:Past Present &Future 立即下载