Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的异步异常处理_Python_Python 3.x_Python Asyncio - Fatal编程技术网

Python中的异步异常处理

Python中的异步异常处理,python,python-3.x,python-asyncio,Python,Python 3.x,Python Asyncio,下面的代码使用asyncio和aiohttp发出异步HTTP请求 import sys import asyncio import aiohttp @asyncio.coroutine def get(url): try: print('GET %s' % url) resp = yield from aiohttp.request('GET', url) except Exception as e: raise Exceptio

下面的代码使用
asyncio
aiohttp
发出异步HTTP请求

import sys
import asyncio
import aiohttp

@asyncio.coroutine
def get(url):
    try:
        print('GET %s' % url)
        resp = yield from aiohttp.request('GET', url)
    except Exception as e:
        raise Exception("%s has error '%s'" % (url, e))
    else:
        if resp.status >= 400:
            raise Exception("%s has error '%s: %s'" % (url, resp.status, resp.reason))

    return (yield from resp.text())

@asyncio.coroutine
def fill_data(run):
    url = 'http://www.google.com/%s' % run['name']
    run['data'] = yield from get(url)

def get_runs():
    runs = [ {'name': 'one'}, {'name': 'two'} ]
    loop = asyncio.get_event_loop()
    task = asyncio.wait([fill_data(r) for r in runs])
    loop.run_until_complete(task)   
    return runs

try:
    get_runs()
except Exception as e:
    print(repr(e))
    sys.exit(1)
由于某些原因,在
get
函数中引发的异常不会被捕获:

Future/Task exception was never retrieved
Traceback (most recent call last):
  File "site-packages/asyncio/tasks.py", line 236, in _step
    result = coro.send(value)
  File "mwe.py", line 25, in fill_data
    run['data'] = yield from get(url)
  File "mwe.py", line 17, in get
    raise Exception("%s has error '%s: %s'" % (url, resp.status, resp.reason))
Exception: http://www.google.com/two has error '404: Not Found'

那么,处理协同路由引发的异常的正确方法是什么呢?

asyncio.wait
实际上并不使用传递给它的
未来
,它只是等待它们完成,然后返回
未来
对象:

协同程序
asyncio.wait(未来,*,循环=None,超时=None,
返回(当=全部完成时)

等待未来和协同路由对象 由期货给出的序列来完成。协同程序将被包装 在任务中。返回两组
Future
:(完成,挂起)

在您实际从
done
列表中的
项目中获得
之前,它们将保持未使用状态。由于您的程序退出时没有使用未来,因此您会看到“exception was never retrieve”(从未检索到异常)消息

对于您的用例,使用它可能更有意义,它将实际使用每个
未来
,然后返回一个聚合所有结果的
未来
(或引发输入列表中未来引发的第一个
异常

输出:

GET http://www.google.com/two
GET http://www.google.com/one
Exception("http://www.google.com/one has error '404: Not Found'",)
请注意,
asyncio.gather
实际上允许您自定义其中一个未来引发异常时的行为;默认行为是引发它遇到的第一个异常,但它也可以只返回输出列表中的每个异常对象:

asyncio.gather(*coros\u或\u futures,loop=None,return\u exceptions=False)

从给定的协程对象返回未来聚合结果 或者说未来

所有期货必须共享相同的事件循环。如果所有任务都完成了 成功返回的future的结果是结果列表(在 原始序列的顺序,不一定是 结果(到达时)如果
返回\u异常
,则 任务被视为成功的结果,并收集在 成绩表;否则,将立即启动第一个引发的异常 传播到返回的未来。

要在中调试或“处理”异常,请执行以下操作:

返回某些结果或引发异常的协同程序:

@asyncio.coroutine
def async_something_entry_point(self):
    try:
        return self.real_stuff_which_throw_exceptions()
    except:
        raise Exception(some_identifier_here + ' ' + traceback.format_exc())
和回调:

def callback(self, future: asyncio.Future):
    exc = future.exception()
    if exc:
        # Handle wonderful empty TimeoutError exception
        if type(exc) == TimeoutError:
            self.logger('<Some id here> callback exception TimeoutError')
        else:
            self.logger("<Some id here> callback exception " + str(exc))

    # store your result where you want
    self.result.append(
        future.result()
    )
def回调(self,future:asyncio.future): exc=future.exception() 如果exc: #处理极好的空TimeoutError异常 如果类型(exc)=超时错误: self.logger('callbackexceptiontimeouterror') 其他: self.logger(“回调异常”+str(exc)) #将结果存储在所需的位置 self.result.append( future.result() )
感谢您的解释,文档对异常处理并不十分清楚,那么如何使用
wait
?是不是有点像asyncio.wait(…)
的收益率?
wait asyncio.wait(…)
也应该工作吗?顺便说一句,如果其中一个例程从未真正启动,同样的问题也会出现。这在我身上发生,两个协同程序(手动)打开一些套接字并尝试
等待.sock\u recv(,)
。如果套接字未切换到非阻塞状态(使用
.setblocking()
),则第二个协同程序不会启动,
键盘中断
会导致“从未检索到任务异常”。在异步函数中,不能使用
产生的收益来解决未来或任务。人们应该等待。这对我来说不清楚。感谢您提供
return\u异常
提示。在执行数百个head请求时,我不希望引发异常,因为其中一个已超时。
def callback(self, future: asyncio.Future):
    exc = future.exception()
    if exc:
        # Handle wonderful empty TimeoutError exception
        if type(exc) == TimeoutError:
            self.logger('<Some id here> callback exception TimeoutError')
        else:
            self.logger("<Some id here> callback exception " + str(exc))

    # store your result where you want
    self.result.append(
        future.result()
    )