【问题标题】:Async socket.send() exception异步 socket.send() 异常
【发布时间】:2018-07-19 17:07:58
【问题描述】:

您好,我的异步循环有以下内容

 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

异常不会导致程序崩溃,但最终会使程序陷入困境以至于无法打印异常。

如何修改当前代码来解决这个问题?

【问题讨论】:

  • run_until_complete 只传播由start_process 协程引发的异常。异常可能发生在transfer 协程之一中,gather 尽职尽责地报告它。如果要忽略异常,可以将restorer.transfer 包装在单独的async def that only does try/await restorer.transfer(...)/except SocketError: pass`中。
  • @user4815162342 我对你在sn-p代码中解释的反应头脑有点困惑?
  • 我现在已将评论扩展为显示代码的答案。它不完整,因为我不了解异常的原因,但它显示了如果在您的情况下可以忽略它。
  • @user4815162342 介意我再打扰你一下吗?
  • 如果您有新问题,请考虑提出单独的问题。如果可能,请包含一个可用于重现问题的最小示例。

标签: python-3.x asynchronous boto3 python-asyncio


【解决方案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;它会被自动调用。

【讨论】:

    猜你喜欢
    • 2011-10-15
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    • 2012-09-27
    • 2011-09-16
    • 2013-10-12
    • 2017-07-26
    • 2018-06-11
    相关资源
    最近更新 更多