异步socket.send()异常

时间:2018-07-19 17:07:59

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

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

 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

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

如何修改当前代码以解决此问题?

1 个答案:

答案 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;它会被自动调用。