一种Pythonic方法,用于更改如何从调用cancel()的位置取消异步IO任务
如何从取消任务的位置更改任务取消的行为 我的梦想是:一种Pythonic方法,用于更改如何从调用cancel()的位置取消异步IO任务,python,python-asyncio,Python,Python Asyncio,如何从取消任务的位置更改任务取消的行为 我的梦想是: task=确保未来(foo()) def foo_完成(任务) 尝试: 返回任务。获取_结果() 除取消错误外,其他错误为e: 何时,为什么=e.args 如果时间==“现在” #做点什么。。。 elif when==“尽快”: #做点别的。。。 其他: #不违约 打印(f“由于{为什么}而取消任务”) task.add_done_回调(foo_done) [...] 任务。取消(“现在”,“这是订单!”) 我可以在调用task.cance
task=确保未来(foo())
def foo_完成(任务)
尝试:
返回任务。获取_结果()
除取消错误外,其他错误为e:
何时,为什么=e.args
如果时间==“现在”
#做点什么。。。
elif when==“尽快”:
#做点别的。。。
其他:
#不违约
打印(f“由于{为什么}而取消任务”)
task.add_done_回调(foo_done)
[...]
任务。取消(“现在”,“这是订单!”)
我可以在调用task.cancel()
之前将一个对象附加到任务,然后再检查它
task=确保未来(foo())
def foo_完成(任务)
尝试:
返回任务。获取_结果()
除取消错误外,其他错误为e:
when=getattr(任务“\u when”,“”)
why=getattr(任务“\u why”,”)
如果时间==“现在”
#做点什么。。。
elif when==“尽快”:
#做点别的。。。
其他:
#不违约
打印(f“由于{为什么}而取消任务”)
task.add_done_回调(foo_done)
[...]
任务。_when=“现在”
任务。_why=“这是订单!”
task.cancel()
但在某些情况下,当我想要捕获正在处理的任务中的CancelError
时,它看起来很笨拙,例如:
async def foo():
#一些东西
尝试:
#一些其他的东西
除取消错误外,如e:
#在这里,我可以轻松访问错误,但无法访问任务:(
[...]
我正在寻找一种更具python风格的方法来完成它。您用与异常相关的数据来修饰
任务的解决方案实际上是一个很好的解决方案。在任务中,您可以使用asyncio.Task.current_Task()
访问正在处理的任务
您还可以使用以下装饰器(未经测试)实现您梦想的语法:
用@propagate\u when
装饰协同程序允许foo\u done
中的代码在处理canceledError
时访问e.when
。缺点是e.when
在任务中不可用-您仍然必须使用current\u task()
。由于这种不一致性,我建议坚持从任务对象读取
若干相关建议:
- 将取消代码放入一个实用程序函数中,该函数存储传递给它的对象,然后调用
task.cancel()
。这种薄薄的封装层应该可以消除当前代码中的“笨拙”感觉
- 使用带前缀的属性名称-短而通用的名称,如
\u,当在将来的版本中可能会导致冲突。(我知道这只是一个示例,但不固定的名称总是有冲突的危险。)
- 用单个对象装饰任务,将实际数据放入其属性中。它使检索更简单、更清晰,并且为您提供了在存储对象上实现方法的选项
考虑到foo_done
是一个同步函数,“现在”和“尽快”有何不同。我意识到“现在”和“尽快”是我想要的糟糕的例子。我的意思是给任务提供取消的原因,并根据它执行一些代码:如果reason=A做这个,如果reason=B,做那个,等等。谢谢!我要找的确实是asyncio.task.current_task()
def propagate_when(fn):
async def wrapped(*args, **kwds):
try:
return await fn(*args, **kwds)
except CancelledError as e:
e.when = getattr(asyncio.Task.current_task(), '_when', None)
raise
return wrapped