你好,我的异步循环有以下内容
async def start_process(restore_items, args, loop):
with GlacierRestorer(args.temp_dir, args.error_log_bucket, loop) as restorer:
restorer.initiate_restore_all(restore_items)
tasks = []
semaphore = asyncio.BoundedSemaphore(4)
for item in restore_items:
tasks.append(asyncio.ensure_future(restorer.transfer(item, semaphore)))
await asyncio.gather(*tasks)
def main():
args = get_args()
restore_items = get_restore_items(args)
for item in restore_items:
print(item.source, ':', item.destination)
try:
loop = asyncio.get_event_loop()
loop.run_until_complete(start_process(restore_items, args, loop))
except KeyboardInterrupt:
pass
我的工作和文件越来越大,我发现我不断 socket.send()异常 阅读文档后,它似乎来自loop.run_until_complete
该异常不会导致程序崩溃,但最终会使它陷入瘫痪,以至于无法打印该异常。
如何修改当前代码以解决此问题?
答案 0 :(得分:1)
run_until_complete
仅传播start_process
内部引发的异常。这意味着,如果start_process
期间的某个时刻发生异常,而start_process
没有捕获到该异常,则run_until_complete(start_process())
将重新引发相同的异常。
在您的情况下,异常最初可能在restorer.transfer()
中的某个地方引发。对gather
的调用返回协程的结果,其中包括引发异常(如果发生异常的话)。
该异常不会导致程序崩溃,但最终会使它陷入瘫痪,以至于无法打印该异常。如何修改当前代码以解决此问题?
理想情况下,您将解决导致异常的原因-也许您一次发送了太多请求,或者您使用的GlacierRestorer
API错误。但是有些例外是无法避免的,例如由网络故障引起的。要忽略此类异常,可以将对restorer.transfer
的调用包装在单独的协程中:
async def safe_transfer(restorer, item, semaphore):
try:
return await restorer.transfer(item, semaphore)
except socket.error as e:
print(e) # here you can choose not to print exceptions you
# don't care about if doing so bogs down the program
在start_process
中,您将称此协程而不是restorer_transfer
:
coros = []
for item in restore_items:
coros.append(safe_transfer(restorer, item, semaphore))
await asyncio.gather(*coros)
请注意,您无需调用asyncio.ensure_future()
即可将协程传递给asyncio.gather
;它会被自动调用。