Как читать из (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:
- В настоящее время asyncio явно не поддерживает ввод-вывод файловой системы, см., например, https://github.com/python/asyncio/wiki/ThirdParty, https://groups.google.com/forum/, каково состояние асинхронного ввода-вывода POSIX (AIO)? и https://github.com/Tinche/aiofiles который наиболее близок к желаемому.
- Все операции ввода-вывода выполняются через HDF5 (библиотека), поэтому для поддержки асинхронного режима, которую вы хотите добавить, потребуется поддержка в HDF5 (библиотека).
Это в основном означает, что h5py вряд ли когда-либо поддержит asyncio.
Вы можете попытаться запустить что-то в потоке, но нет никаких гарантий, что он будет работать хорошо, хотя, как я упоминал, HDF5 контролирует ввод-вывод, и вы захотите убедиться, что вы не столкнетесь ни с одним из его элементов управления блокировкой. Вы, вероятно, захотите понять, какой режим файлов, упомянутый по адресу http://docs.h5py.org/en/latest/high/file.html, подойдет вам лучше всего. Может быть, вы могли бы рассмотреть другие альтернативы, такие как многопроцессорность или concurrent.futures?