Правильное использование / ограничения использования, nest_asyncio? - PullRequest
0 голосов
/ 14 января 2020

Я работаю над созданием ранее синхронизированного c веб-сервера как syn c. Большинство моих функций являются syn c, и я хотел бы просто сделать asyn c вызовы из существующего кода, чтобы избежать asyn c creep. nest_asyncio, по-видимому, позволяет это сделать, заставляя run_until_complete повторно входить.

Однако, хотя это работает для одного повторного вызова, я получаю тупик с двумя:

import asyncio
import functools
import time
from random import random
import nest_asyncio
nest_asyncio.apply()

def sync(corot, loop=None):
    """
    Make a synchronous function from an asynchronous one.
    :param corot:
    :return:
    """
    if loop is None:
        loop = asyncio.get_event_loop()
    result, = loop.run_until_complete(asyncio.gather(corot))
    return result

async def sync_to_corountine(func, *args, **kw):
    """
    Make a coroutine from a synchronous function.
    """
    try:
        return func(*args, *kw)
    finally:
        # every async needs an await.
        await asyncio.sleep(0)




def main():
    async def background(timeout):
        await asyncio.sleep(timeout)
        print(f"Background: {timeout}")

    loop = asyncio.get_event_loop()
    # Run some background work to check we are never blocked
    bg_tasks = [
        loop.create_task(background(i))
        for i in range(10)
    ]



    async def long_running_async_task(result):
        # Simulate slow IO
        print(f"...START long_running_async_task [{result}]")
        await asyncio.sleep(1)
        print(f"...END   long_running_async_task [{result}]")
        return result

    def sync_function_with_async_dependency(result):
        print(f"...START sync_function_with_async_dependency [{result}]")
        result = sync(long_running_async_task(result), loop=loop)
        print(f"...END   sync_function_with_async_dependency [{result}]")
        return result

    # Call sync_function_with_async_dependency
    # One reentrant task is OK
    # Multiple reentrant tasks=>fails to exit
    n = 2
    for i in range(n):
        bg_tasks.append(sync_to_corountine(sync_function_with_async_dependency, i))
    # for i in range(n):
    #     bg_tasks.append(long_running_async_task(i))

    # OK
    # bg_tasks.append(long_running_async_task(123))
    # bg_tasks.append(long_running_async_task(456))

    task = asyncio.gather(*bg_tasks)  # , loop=loop)
    loop.run_until_complete(task)

if __name__ == '__main__':
    main()

...START sync_function_with_async_dependency [0]
...START sync_function_with_async_dependency [1]
Background: 0
...START long_running_async_task [0]
...START long_running_async_task [1]
Background: 1
...END   long_running_async_task [0]
...END   long_running_async_task [1]
...END   sync_function_with_async_dependency [1]
Background: 2
Background: 3
Background: 4

... нам не хватает

...END   sync_function_with_async_dependency [0]

Правильно ли я использую nest_asyncio?

...