首页 文章

是否可以在后台启动asyncio事件循环而不产生线程或进程?

提问于
浏览
3

我有一个在Python 3.5中实现的服务,应该定期通过网络加载文件 . 我想避免在加载时阻塞主线程 . 为了避免将线程和共享内存的复杂性引入我的应用程序,我想使用带有asyncio包的事件循环来检测它 .

为了运行一个事件循环,我找到了 AbstractEventLoop.run_forever()AbstractEventLoop.run_until_complete(future) 方法,但两者似乎都在调用时阻塞了主线程 . 无论如何我使用线程的唯一方法是使用事件循环没有意义 .

所以我的问题是:是否可以在后台启动asyncio事件循环而不产生线程或进程?

2 回答

  • 1

    您可以使用 run_in_executor 方法 . 使用此方法运行的每个函数都在自己的线程中运行(并行) .

    AbstractEventLoop.run_in_executor()方法可以与线程池执行程序一起使用,以在不同的线程中执行回调,从而不阻塞事件循环的线程 . executor参数应该是Executor实例 . 如果执行程序为None,则使用缺省执行程序 .

    例如:

    import asyncio
    
    def load_file_over_network(file_name):
        # do the file loading
        pass
    
    loop = asyncio.get_event_loop()
    file_name = 'FILE_NAME'
    
    # load the file without blocking
    loop.run_in_executor(None, load_file_over_network, file_name)
    
    # do some other stuff in the main thread
    # while the synchronous code above is running in other threads, the event loop
    # can go do other things
    
    # load the file again without blocking
    loop.run_in_executor(None, load_file_over_network, file_name)
    

    希望这有用:)

  • 2

    如果你的整个程序在没有 asyncio 的事件循环的情况下运行,那么在新的事件循环中只运行一个任务并没有多大意义 . 相反,尝试使用复杂得多的concurrent.futures库 . 任何被调用的任务都会立即返回 Future 实例,该实例具有 .done().result() 方法:

    import time
    from concurrent.futures.thread import ThreadPoolExecutor
    
    
    def fetcher():
        print("fetching...")
        time.sleep(2)
        print("got it!")
        return 42
    
    
    with ThreadPoolExecutor(max_workers=10) as executor:
        fut = None
        for i in range(100):
            if i % 10 == 2:
                fut = executor.submit(fetcher)
            print(i, fut)
            if fut and fut.done():
                result = fut.result()  # can raise an error
                print("Done! Got:", result)
                fut = None
            time.sleep(0.5)
    

相关问题