- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
万一gather
的一项任务引发异常,其他人仍然可以继续。
嗯,这不完全是我需要的。我想区分致命的错误和需要取消所有剩余任务的错误,以及不是而是应该在允许其他任务继续的同时记录的错误。
这是我实现这一点的失败尝试:
from asyncio import gather, get_event_loop, sleep
class ErrorThatShouldCancelOtherTasks(Exception):
pass
async def my_sleep(secs):
await sleep(secs)
if secs == 5:
raise ErrorThatShouldCancelOtherTasks('5 is forbidden!')
print(f'Slept for {secs}secs.')
async def main():
try:
sleepers = gather(*[my_sleep(secs) for secs in [2, 5, 7]])
await sleepers
except ErrorThatShouldCancelOtherTasks:
print('Fatal error; cancelling')
sleepers.cancel()
finally:
await sleep(5)
get_event_loop().run_until_complete(main())
(这里的
finally await sleep
是为了防止解释器立即关闭,这会自行取消所有任务)
cancel
在
gather
实际上并没有取消它!
PS C:\Users\m> .\AppData\Local\Programs\Python\Python368\python.exe .\wtf.py
Slept for 2secs.
Fatal error; cancelling
Slept for 7secs.
我对这种行为感到非常惊讶,因为它似乎与
the documentation 矛盾。 ,其中指出:
asyncio.gather(*coros_or_futures, loop=None, return_exceptions=False)
Return a future aggregating results from the given coroutine objects or futures.
(...)
Cancellation: if the outer Future is cancelled, all children (that have not completed yet) are also cancelled. (...)
最佳答案
您的实现的问题在于它在 sleepers.cancel()
已经引发之后调用 sleepers
。从技术上讲,gather()
返回的 future 处于完成状态,因此它的取消必须是 no-op。
要更正代码,您只需要自己取消 child ,而不是相信 gather
的 future 会这样做。当然,协程本身不可取消,因此您需要先将它们转换为任务(gather
无论如何都会这样做,因此您无需做额外的工作)。例如:
async def main():
tasks = [asyncio.ensure_future(my_sleep(secs))
for secs in [2, 5, 7]]
try:
await asyncio.gather(*tasks)
except ErrorThatShouldCancelOtherTasks:
print('Fatal error; cancelling')
for t in tasks:
t.cancel()
finally:
await sleep(5)
I am very surprised by this behavior since it seems to be contradictory to the documentation[...]
gather
最初的绊脚石是它并没有真正运行任务,它只是一个等待它们完成的助手。出于这个原因,
gather
如果其中一些任务因异常而失败,则不会取消剩余的任务——它只是放弃等待并传播异常,让剩余的任务在后台继续进行。这是
reported as a bug ,但不是为了向后兼容而修复的,因为行为被记录下来并且从一开始就没有改变。但这里我们还有另一个问题:文档明确 promise 能够取消返回的 future 。您的代码正是这样做的,但它不起作用,原因很明显(至少我花了一段时间才弄明白,并且需要阅读
source )。事实证明,
Future
的契约实际上阻止了它的工作。当你调用
cancel()
时,
gather
返回的 future 已经完成,取消一个完成的 future 是没有意义的,它只是 no-op。 (原因是一个完整的 future 有一个明确定义的结果,可以被外部代码观察到。取消它会改变它的结果,这是不允许的。)
await sleepers
完成之前执行了取消操作,它就会起作用。但是,它具有误导性,因为它似乎允许在其可等待提升之一的重要用例中取消
gather()
,但实际上不允许。
gather
时会出现这样的问题,这就是为什么许多人急切地等待(没有双关语)三重奏风格的托儿所
in asyncio 的原因。
关于python - 如果一个任务失败,如何取消收集中的所有剩余任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59073556/
我正在运行一个带有 while 约束的 SQL 查询,其中包含一些“id”。例如: SELECT table.id FROM TableOne table WHERE table.id IN (1,
我正在寻找在替换其中一个元素后打印元素列表的最正确方法。我可以按如下方式做,但显然很困惑。 #!/usr/bin/python import sys file = open(sys.argv[1])
这个问题在这里已经有了答案: How wide is the default `` margin? (4 个答案) How do I remove the top margin in a web
当我尝试使用命令安装 rvm 时::(I am Using UBUNTU 12.04 LTS) curl -L https://get.rvm.io | bash -s 当我尝试与简单用户相同的命令时
我使用 GOPro 工作人员 6 个月前发送给我的命令,通过终端(在 Gopro 网络上)使用 Gopro Hero3 拍摄照片/视频。有效。但是,在过去的一个月里,我一直在尝试再次执行此操作,并且不
尽管知道我不应该关闭应用程序按钮,但我仍然这样做。完成所有 Activity 后,我调用 finish() 方法,它们调用析构函数和所有内容。用户的行为也是正确的。但我想知道为什么还有 5 个打开的线
当我在 Rest Controller 中的类级别启用 @Validated spring 注释时,会生成 2 个验证上下文(每个验证上下文都有不同的前缀)。 @Validated 注释是必需的,因为
在旧的 API 中,剩余的允许容量显然作为 X-Ratelimit-Remaining 返回HTTP header 。 然而,current version's documentation对此一无所获
我一直在使用 Service Fabric 一段时间,成功构建、部署和测试了多个服务,但我刚刚完成构建的服务在部署时失败(请参阅下面的错误)。在诊断中,我尝试使用 VS 模板(没有代码更改)创建和部署
这个问题在这里已经有了答案: 关闭 12 年前。 Possible Duplicate: Progress unit in ProgressDialog 如何覆盖进度条进度消息,即 61/100 到
我正在用 Objective-C (Cocoa) 编写命令行实用程序的前端。我需要解析输出以检查不同类型的消息。有两种基本类型;信息消息和下载状态消息。信息消息始终以以下内容之一开头:INFO:、WA
我是一名优秀的程序员,十分优秀!