0

我正在尝试编写一个基本上并行运行两件事的小 Python 脚本。我来自 JavaScript 并尝试使用 Python 的 async/await 协程功能,但我在让它按预期工作时遇到了一些麻烦。

让前两个函数并行运行很容易。我遇到的问题与捕获语法错误有关。

具体来说,我试图在我的一个函数中添加一些数学,但 Python 似乎只是停留在这一步(在工作之前打印,在他们没有工作之后)。我将我的问题追溯到没有像我预期的那样冒泡的语法异常,特别是如果它们发生在“期货”中,asyncio 似乎隐藏了错误。我认为这就是我的问题所在,但我已经花了很长时间试图按照我的预期来捕捉错误。

我尝试将整个有问题的协程包装在try/except中,但这似乎破坏了我的其他协程(似乎打破了我对协程如何工作的假设)。

#!/usr/bin/env python3

import asyncio

async def other():
    while True:
        await asyncio.sleep(1)
        print('foobar')
        
async def test():
    try:
        while True:
            a = undefinedVariable
    except:
        print("Why doesn't this always catch??")

# catches as expected
asyncio.get_event_loop().run_until_complete(asyncio.wait([test()]))

# doesn't catch, fills screen with "foobar" lines, once a second, runs forever
asyncio.get_event_loop().run_until_complete(asyncio.wait([test(), other()]))

# Trying other things...
# Error:
# RuntimeError: no running event loop
# sys:1: RuntimeWarning: coroutine 'test' was never awaited"
asyncio.get_event_loop().run_until_complete(asyncio.wait([asyncio.create_task(t()) for t in [test, other]]))

运行一个有问题的协程按预期工作。

将它与另一个不会出错的协程结合起来会使另一个协程停止尊重asyncio.sleep.

我曾经到一个点,如果我按 Ctrl+C,它将停止打印“foobar”,打印语法错误,然后退出,但我未能捕获该代码并且它丢失了撤消。

我觉得我错过了一些简单的东西。任何指针将不胜感激。

4

1 回答 1

0

我在文档中找到了asyncio.run()应该用作“主要”入口点并处理所有循环创建和清理的参考,所以我尝试了它。

使用它比事件循环的东西更清楚一点。以下做我想要的。

asyncio.run(asyncio.wait([test(), other()], return_when=asyncio.FIRST_COMPLETED))

我不明白为什么当我return_when=asyncio.FIRST_COMPLETED早些时候尝试时它一直在运行。也许我错过了其他一些错字。

混淆的一个来源是协程不会运行,除非有什么在等待它们。

不确定这是否有助于将来的其他人。感谢所有看过的人。

于 2020-09-27T23:53:44.263 回答