简体   繁体   中英

How to write a class instantiable form both synchronous and asyncio code?

I am trying to build a class that's instantiable from both "standard" (ie: non asyncio ) code and for asyncio coroutine.

Specifically some methods need to spawn subprocess es and wait for completion. Difference is that, while subprocess is running I shouldn't block the whole program (other coroutines, if they exist, should be able to run).

This boils down to use plain:

from subprocess import run
r = run(arg[0], args)

in "standard" code and:

from asyncio import create_subprocess_exec
r = await create_subprocess_exec(*args)
t = await r.wait()

problem is I cannot await from standard non- async method even if a loop is running (I can test if loop is running to discriminate, but I don't know how to hook to the running loop, if any).

What you want to do is not supported by asyncio, and it might not be possible at all. Sync and async functions differ not only in function names, but in fundamental semantics of values and function calls.

Superficially you could do this:

def _run_subprocess_sync(args):
    from subprocess import run
    return run(args[0], args)

async def _run_subprocess_async(args):
    from asyncio import create_subprocess_exec
    r = await create_subprocess_exec(*args)
    return await r.wait()

def run_subprocess(args):
    if asyncio.get_event_loop() is not None and asyncio.get_event_loop().is_running():
        return _run_subprocess_async(args)
    else:
        return _run_subprocess_sync(args)

Note that it's ok that in the async case run_subprocess doesn't await the call to _run_subprocess_async because it will return a coroutine object which its caller (presumably an async def function) will await.

The problem is that this approach won't get you very far because it will require similar if s at every level of the hierarchy. For example, if you have a function that calls run_subprocess and does something with its result, it will similarly have to come in two variants, a sync and an async one, and a switch between the two.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM