Python: Aioimaplib 捕获异常
Python: Aioimaplib catch exceptions
我正在尝试使用 aioimaplib 异步检查多个 imap 登录信息。
只要 imap 服务器可访问和/或客户端不超时,此代码就可以工作。
捕获异常的正确方法是什么?
异常示例:
ERROR:asyncio:Task exception was never retrieved future: <Task finished coro=<BaseEventLoop.create_connection() done, defined at G:\WinPython-3.5.4\python-3.5.4.amd64\lib\asyncio\base_events.py:679> exception=TimeoutError(10060, "Connect call failed ('74.117.114.100', 993)")>
代码:
account_infos = [
# User Password Server
('user1@web.com', 'password1', 'imap.google.com'),
('user2@web.com', 'password2', 'imap.yandex.com'),
('user3@web.com', 'password3', 'imap.server3.com'),
]
class MailLogin:
def __init__(self):
self.loop = asyncio.get_event_loop()
self.queue = asyncio.Queue(loop=self.loop)
self.max_workers = 2
async def produce_work(self):
for i in account_infos:
await self.queue.put(i)
for _ in range(max_workers):
await self.queue.put((None, None, None))
async def worker(self):
while True:
(username, password, server) = await self.queue.get()
if username is None:
break
while True:
try:
s = IMAP4_SSL(server)
await s.wait_hello_from_server()
r = await s.login(username, password)
await s.logout()
if r.result != 'NO':
print('Information works')
except Exception as e:
# DOES NOT CATCH
print(str(e))
else:
break
def start(self):
try:
self.loop.run_until_complete(
asyncio.gather(self.produce_work(), *[self.worker() for _ in range(self.max_workers)],
loop=self.loop, return_exceptions=True)
)
finally:
print('Done')
if __name__ == '__main__':
MailLogin().start()
有 several ways 可以执行此操作,但 TimeoutError
可能卡在您的 except
中。你看不到它,因为 str(e) 是一个空字符串。
可以看到asyncio的堆栈enabling debug mode。
首先,您可以像以前一样捕获异常:
async def fail_fun():
try:
imap_client = aioimaplib.IMAP4_SSL(host='foo', timeout=1)
await imap_client.wait_hello_from_server()
except Exception as e:
print('Exception : ' + str(e))
if __name__ == '__main__':
get_event_loop().run_until_complete(fail_fun())
其次,您可以在 run_until_complete
捕获异常
async def fail_fun():
imap_client = aioimaplib.IMAP4_SSL(host='foo', timeout=1)
await imap_client.wait_hello_from_server()
if __name__ == '__main__':
try:
get_event_loop().run_until_complete(fail_fun())
except Exception as e:
print('Exception : ' + str(e))
建立连接并用 create_task
包装 loop.create_connection
协程:我们想在 IMAP4 构造函数和 __init__
should return None 中建立连接。
所以如果你的主机有一个错误的值,你可以之前测试它,或者等待超时:
socket.gaierror: [Errno -5] No address associated with hostname
如果主机在超时前没有响应,您可以提高超时时间。并且如果连接过程中连接丢失,可以在IMAP4构造函数中添加连接丢失回调。
我正在尝试使用 aioimaplib 异步检查多个 imap 登录信息。 只要 imap 服务器可访问和/或客户端不超时,此代码就可以工作。
捕获异常的正确方法是什么?
异常示例:
ERROR:asyncio:Task exception was never retrieved future: <Task finished coro=<BaseEventLoop.create_connection() done, defined at G:\WinPython-3.5.4\python-3.5.4.amd64\lib\asyncio\base_events.py:679> exception=TimeoutError(10060, "Connect call failed ('74.117.114.100', 993)")>
代码:
account_infos = [
# User Password Server
('user1@web.com', 'password1', 'imap.google.com'),
('user2@web.com', 'password2', 'imap.yandex.com'),
('user3@web.com', 'password3', 'imap.server3.com'),
]
class MailLogin:
def __init__(self):
self.loop = asyncio.get_event_loop()
self.queue = asyncio.Queue(loop=self.loop)
self.max_workers = 2
async def produce_work(self):
for i in account_infos:
await self.queue.put(i)
for _ in range(max_workers):
await self.queue.put((None, None, None))
async def worker(self):
while True:
(username, password, server) = await self.queue.get()
if username is None:
break
while True:
try:
s = IMAP4_SSL(server)
await s.wait_hello_from_server()
r = await s.login(username, password)
await s.logout()
if r.result != 'NO':
print('Information works')
except Exception as e:
# DOES NOT CATCH
print(str(e))
else:
break
def start(self):
try:
self.loop.run_until_complete(
asyncio.gather(self.produce_work(), *[self.worker() for _ in range(self.max_workers)],
loop=self.loop, return_exceptions=True)
)
finally:
print('Done')
if __name__ == '__main__':
MailLogin().start()
有 several ways 可以执行此操作,但 TimeoutError
可能卡在您的 except
中。你看不到它,因为 str(e) 是一个空字符串。
可以看到asyncio的堆栈enabling debug mode。
首先,您可以像以前一样捕获异常:
async def fail_fun():
try:
imap_client = aioimaplib.IMAP4_SSL(host='foo', timeout=1)
await imap_client.wait_hello_from_server()
except Exception as e:
print('Exception : ' + str(e))
if __name__ == '__main__':
get_event_loop().run_until_complete(fail_fun())
其次,您可以在 run_until_complete
async def fail_fun():
imap_client = aioimaplib.IMAP4_SSL(host='foo', timeout=1)
await imap_client.wait_hello_from_server()
if __name__ == '__main__':
try:
get_event_loop().run_until_complete(fail_fun())
except Exception as e:
print('Exception : ' + str(e))
建立连接并用 create_task
包装 loop.create_connection
协程:我们想在 IMAP4 构造函数和 __init__
should return None 中建立连接。
所以如果你的主机有一个错误的值,你可以之前测试它,或者等待超时:
socket.gaierror: [Errno -5] No address associated with hostname
如果主机在超时前没有响应,您可以提高超时时间。并且如果连接过程中连接丢失,可以在IMAP4构造函数中添加连接丢失回调。