Как читать из (hdf5) файла в асинхронных контекстах?

В последнее время я немного поигрался с асинхронными функциями Python 3. В целом, я доволен синтаксисом 3.6 и, конечно, повышением производительности, которое вы получаете. Один из захватывающих проектов, разворачивающихся вокруг ASGI Стандарт на мой взгляд это старлетка. У меня запущен пример приложения, в котором я читаю данные из hdf5 файл. h5py пока не поддерживает асинхронный ввод-вывод. В связи с этим возникает вопрос: имеет ли смысл то, что я здесь делаю? Насколько я понимаю, этот код работает синхронно в конце концов. Каков рекомендуемый способ ввода / вывода в асинхронных контекстах?

async def _flow(indexes):
    print('received flow indexes %s ' %indexes)
    # uses h5py under the hood
    gr = GridH5ResultAdmin(gridadmin_f, results_f)
    t = gr.nodes.timeseries(indexes=indexes)
    data = t.only('s1').data
    # data is a numpy array
    return data['s1'].tolist()

@app.route('/flow_velocity')
async def flow_results(request):

    indexes_list = [[2,3,4,5], [6,7,8,9], [10,11,12,13]]

    tasks = []
    loop = asyncio.get_event_loop()
    t0 = datetime.datetime.now()
    for indexes in indexes_list:
        print('Start getting indexes %s' % indexes)
        # Launch a coroutine for each data fetch
        task = loop.create_task(_flow(indexes))
        tasks.append(task)

    # Wait on, and then gather, all data
    flow_data = await asyncio.gather(*tasks)
    dt = (datetime.datetime.now() - t0).total_seconds()
    print('elapsed time: {} [s]'.format(dt))

    return JSONResponse({'flow_velocity': flow_data})

Логирование:

INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
Start getting indexes "[2, 3, 4, 5]"
Start getting indexes "[6, 7, 8, 9]"
Start getting indexes "[10, 11, 12, 13]"
received flow indexes [2, 3, 4, 5] 
received flow indexes [6, 7, 8, 9] 
received flow indexes [10, 11, 12, 13]
elapsed time: 1.49779 [s]

0 ответов

К сожалению с h5py модуль, который вы не можете использовать asyncioто, что вы здесь делаете, в основном последовательное, потому что если часть ввода / вывода не может быть выполнена асинхронно, то остальная часть вашего асинхронного кода не имеет большого значения

https://github.com/h5py/h5py/issues/837

Резюме из этой темы

Таким образом, есть две отдельные проблемы с добавлением поддержки asyncio:

  1. В настоящее время asyncio явно не поддерживает ввод-вывод файловой системы, см., например, https://github.com/python/asyncio/wiki/ThirdParty, https://groups.google.com/forum/, каково состояние асинхронного ввода-вывода POSIX (AIO)? и https://github.com/Tinche/aiofiles который наиболее близок к желаемому.
  2. Все операции ввода-вывода выполняются через HDF5 (библиотека), поэтому для поддержки асинхронного режима, которую вы хотите добавить, потребуется поддержка в HDF5 (библиотека).

Это в основном означает, что h5py вряд ли когда-либо поддержит asyncio.

Вы можете попытаться запустить что-то в потоке, но нет никаких гарантий, что он будет работать хорошо, хотя, как я упоминал, HDF5 контролирует ввод-вывод, и вы захотите убедиться, что вы не столкнетесь ни с одним из его элементов управления блокировкой. Вы, вероятно, захотите понять, какой режим файлов, упомянутый по адресу http://docs.h5py.org/en/latest/high/file.html, подойдет вам лучше всего. Может быть, вы могли бы рассмотреть другие альтернативы, такие как многопроцессорность или concurrent.futures?

Другие вопросы по тегам