Как использовать python3 asyncio, ну, asyn c io? - PullRequest
1 голос
/ 15 января 2020

Моя python 3.6 программа должна записывать некоторые файлы асинхронно, чтобы она могла перекрывать запись с вычислениями в другом потоке. Программа использует библиотеку модулей C для вычисления структуры и вызывает функцию в этой библиотеке для ее сохранения. Ниже приведен эскиз:

async def save_thing(thing_ref):
    my_lib.save_thing(thing_ref)

def main():
    handles = []
    for i in [1, 2, 3]:
        thing_ref = my_lib.compute_thing(i)
        handle = save_thing(thing_ref)
        handles.append(handle)

    await_all(handles)
    # ... proceed with program ...

mylib.save_thing освобождает GIL: при входе он вызывает PyEval_SaveThread(), а при выходе - PyEval_RestoreThread(). Выше я пропустил явное увеличение количества ссылок на thing_ref, но я ожидаю, что я буду управлять счетами ссылок явно, чтобы поддерживать thing_ref до тех пор, пока save_thing не будет сделано.

Может кто-нибудь, пожалуйста, помогите мне выведите sh из этого эскиза, чтобы показать мне механизм, который мне нужно включить, чтобы тело my_lib.save_thing () выполнялось одновременно в другом потоке с python l oop? Я пытаюсь понять роль циклов событий, модуля asyncio, GIL и потоков python в целом. Я подозреваю, что простое освобождение GIL не приведет к тому, что интерпретатор основного потока возобновит работу в этот момент, и мне неясно, как это сделать.

1 Ответ

0 голосов
/ 26 февраля 2020

Если я правильно понял, и save_thing (thing_ref) является ожидаемым, то вы можете сделать это

import asyncio



async def save_thing(thing_ref):
    await asyncio.sleep(1)                # so you can see this works
    # await my_lib.save_thing(thing_ref)  # if this is awaitable
    return thing_ref


def compute_thing(i):
    return i




def main():
    loop = asyncio.get_event_loop()
    handles = []
    for i in [1, 2, 3]:
        thing_ref = compute_thing(i)
        handle = loop.run_until_complete(save_thing(thing_ref))
        handles.append(handle)
    print(handles)


if __name__ == "__main__":
    main()

output

[1, 2, 3 ]

...