【问题标题】:How to write a class instantiable form both synchronous and asyncio code?如何编写同步和异步代码的类实例化形式?
【发布时间】:2019-07-24 09:51:27
【问题描述】:

我正在尝试构建一个可从“标准”(即:非 asyncio)代码和 asyncio 协程实例化的类。

特别是一些方法需要产生subprocesses 并等待完成。 不同之处在于,当子进程运行时,我不应该阻塞整个程序(其他协程,如果存在,应该能够运行)。

这归结为使用plain:

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

在“标准”代码中:

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

问题是我不能从标准的非async 方法await 即使循环正在运行(我可以测试循环是否正在运行以区分,但我不知道如何挂钩到正在运行的循环,如果有的话)。

【问题讨论】:

  • 这与“可实例化的类”有何关系?什么课程和什么问题?
  • @RomanPerekhrest:当然,类在两种环境中都是可实例化的,但是,除非我做某事,否则它会在子进程处于活动状态时阻塞整个程序。因此,我需要一些方法来有条件地以“异步友好”的方式运行子进程,否则该类的某些方法将出现异常(阻止其他所有方法)。

标签: python python-3.x subprocess python-asyncio


【解决方案1】:

asyncio 不支持您想要做的事情,而且可能根本不可能。同步和异步函数不仅在函数名称上有所不同,而且在值和函数调用的基本语义上也有所不同。

表面上你可以这样做:

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)

请注意,在异步情况下,run_subprocess 不会等待对_run_subprocess_async 的调用,因为它会返回一个协程对象,它的调用者(可能是一个async def 函数)将等待。

问题是这种方法不会让你走得太远,因为它需要在层次结构的每一层都使用类似的ifs。例如,如果您有一个函数调用 run_subprocess 并对其结果进行处理,那么它同样必须有两个变体,一个同步和一个异步,以及在两者之间切换。

【讨论】:

  • 您的代码看起来像一个竞争条件。如果事件循环在 if 和异步调用之间停止怎么办
  • @lhk 请记住,asyncio 基本上是单线程的。 get_event_loop() 返回与当前线程关联的事件循环,并且这种关联不能从不同的线程更新。因此,如果它返回 non-None,则意味着事件循环要么在此线程中运行,要么根本不运行。在这两种情况下,事件循环都不能在if 和异步调用之间停止运行,因为loop.stop() 只能从运行事件循环的线程中调用。
  • 哦,这很有趣。我认为一旦没有执行或等待的代码,循环就会自动停止。不知道你必须明确停止它
  • @lhk 你想的没错(除非使用了run_foreverequivalent,但逻辑仍然存在:要么我们在inside 循环中运行,要么循环在'没有运行。如果是前者,循环不能在if和异步调用之间关闭(记住它在同一个线程中)。如果是后者,循环不能启动if 和同步调用之间运行,因为我们再次在同一个线程中,而且我们没有启动它。当一切都是单线程时,没有人可以与 竞争>.
  • 哦,真的。这就说得通了。感谢您的解释:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-06
  • 1970-01-01
  • 2017-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多