我在使用此代码时遇到了小麻烦:
try:
return await asyncio.wait_for(tcp_command(cmd), timeout=timeout)
except (OSError, asyncio.TimeoutError) as err:
print(f"Network problem: {err}")
发生超时时,它仅打印“网络问题:”。这是由附加到引发的asyncio.TimeoutError的空值引起的。
# inside wait_for():
raise futures.TimeoutError()
分别对TimeoutError
进行处理很容易,但是我发现原始结构很惯用,现在一个核心库将其破坏了。是否有充分的理由呢?我的假设是-打印异常应该给我们一个出了什么错的线索-正确吗?
答案 0 :(得分:3)
有充分的理由吗?
是的,您希望收到TimeoutError
什么样的消息? “发生超时”?异常本身是不言自明的,不需要这种冗余。
我的假设是-打印异常应该给我们一个出了什么错的线索-正确吗?
是,不是。线索?是。完整信息?否。异常消息不是强制性的。异常的类型也是重要的信息。在许多情况下,消息本身甚至更多。
因此,首先:首先使用print
是错误的。 Python具有非常丰富的日志记录支持。例如logger.exception(str(exc))
解决了您的问题,因为它记录了除消息外的整个回溯。至少默认情况下可以自定义。
但是,如果您仍然想使用print
,请考虑记录整个回溯:
import traceback
# traceback.print_exc()
print(traceback.format_exc())
如果整个回溯太大,那么您始终可以简单地打印异常的类名:
# print(f'[{type(exc).__name__}] {exc}')
print(f'[{type(exc)}] {exc}')
或通过例外进行自定义:
try:
return await asyncio.wait_for(tcp_command(cmd), timeout=timeout)
except OSError as err:
print(f"Network problem: {err}")
except asyncio.TimeoutError:
print('Timeout occured')
答案 1 :(得分:1)
期望异常将提供解释该问题的消息不是Python中常规异常合同的一部分。对于诸如OSError
之类的系统异常,程序必须能够获取操作系统提供的错误消息,这是事实,因为程序没有资格根据代码或异常子类型猜测消息。
但是更多的基本语言异常不能那样工作。以KeyError
提出的dict.__getitem__
为例:
>>> try:
... d[123]
... except KeyError as err:
... print(f"Dict problem: {err}")
...
Dict problem: 123
从这个意义上讲,TimeoutError
更像KeyError
而不是OSError
。当您抓到TimeoutError
时,您确切地知道发生了什么-超时。您通常希望基于发生超时的事实来做某事,而不是仅向用户显示一条消息。即使您确实想提供一条消息,也要使用对您的应用程序有意义的消息,而不是Python提供的通用消息。与OSError
相反,在except
中,除了显示来自操作系统的消息外,您通常无能为力,并且该消息对于调查根本问题可能具有无可估量的价值。
总而言之,问题在于您在同一个try:
return await asyncio.wait_for(tcp_command(cmd), timeout=timeout)
except OSError as err:
print(f"Network problem: {err}")
except asyncio.TimeoutError:
print("Operation timed out")
子句中捕获了两个根本不同的异常,这使您陷入麻烦。我将这样重组代码:
For i = 1 To lRow Step 10
Range("B" & i & ":B" & i + 9).Value = Range("A1:A10").Value
Next i