Multiprocessing中的Python asyncio。每个进程一个事件循环

时间:2018-11-12 18:58:04

标签: python python-multiprocessing python-asyncio

我正在为我的团队编写一个函数,该函数将从云中下载一些数据。该函数本身是一个常规的python函数,但在后台使用了asyncio。因此,我在函数中创建了一个事件循环,并让异步协程同时执行下载。数据下载后,我对其进行处理并返回结果。

当我从其他Python函数调用它时,我的函数按预期工作。但是,当我尝试使用多处理对其进行并行化时,偶尔会看到一些IOErrors。

我尝试搜索有关如何实现此目标的示例,但找不到任何示例。我只看到使用concurrent.futures并让事件循环的run_in_executor进行并行化的建议。这对我来说不是一个选择,因为我想对团队隐藏所有异步内容,只向他们提供可以从代码中调用的简单Python函数(可能在多处理中)。我在网上看到过争论,为什么这是一个坏主意,为什么我不应该隐藏异步的东西,但就我而言,我的团队并不是精明的程序员。他们永远不会使用(或费力去理解)asyncio,因此一个简单的python函数最适合我们。

最后,这是一个伪示例,显示了我正在尝试做的事情:

import asyncio
import aiohttp
from typing import List

async def _async_fetch_data(symbol: str) -> bytes:
    '''
    Download stock data for given symbol from yahoo finance.
    '''

    async with asyncio.BoundedSemaphore(50), aiohttp.ClientSession() as session:
        try:
            url = f'https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?symbol={symbol}&period1=0&period2=9999999999&interval=1d'

            async with session.get(url) as response:
                return await response.read()
        except:
            return None

def fetch_data(symbols: List[str]) -> List[bytes]:
    ''' 
    Gateway function that wraps the under the hood async stuff 
    '''

    coroutine_list = [_async_fetch_data(x) for x in symbols]
    if len(coroutine_list) == 0:
        return []

    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    data = loop.run_until_complete(asyncio.wait(coroutine_list))[0]
    loop.close()
    return [d.result() for d in data if d.result() is not None]

如果我按以下方式运行,这行得通

>>> data = fetch_data(['AAPL', 'GOOG'])

但是我担心它在运行时能否正常运行

>>> from multiprocessing import Pool as ProcessPool
>>> with ProcessPool(2) as pool:
        data = [j for i in pool.map(fetch_data, [['AAPL', 'GOOG'], ['AMZN', 'MSFT']]) for j in i]

我偶尔会看到IOError,但是我无法重现它们,并且我不确定是否是因为我将异步与多处理混合在一起或其他原因。

0 个答案:

没有答案