python 使用 raise 处理异常,但为什么需要 runtimeerror
python exception handling with raise but why runtimeerror is needed
我正在尝试从 Python 一本书中理解这段代码。
def client(hostname, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.connect((hostname, port))
print('Client socket name is {}'.format(sock.getsockname()))
delay = 0.1 # seconds
text = 'This is another message'
data = text.encode('ascii')
while True:
sock.send(data)
print('Waiting up to {} seconds for a reply'.format(delay))
sock.settimeout(delay)
try:
data = sock.recv(MAX_BYTES)
except socket.timeout as exc:
delay *= 2 # wait even longer for the next request
if delay > 2.0:
raise RuntimeError('I think the server is down') from exc
else:
break # we are done, and can stop looping
print('The server says {!r}'.format(data.decode('ascii')))
这一行:
raise RuntimeError('I think the server is down') from exc
我知道“raise”可以引发异常,而“exc”包含异常。但我不明白为什么我们需要“RuntimeError('I think the server is down')”。让我们的代码有这一行而不是只有“raise”语句有什么意义。
简而言之:
两者的输出不同:
raise
给出这个输出:
RuntimeError: No active exception to reraise #or whatever exception is active
鉴于:
raise RuntimeError('I think the server is down')
给出:
RuntimeError: I think the server is down
在后者中,您指定了一个运行时错误,而在第一个中,您只是 运行 来自异常的错误。
附加示例:
为了进一步解释,请考虑以下示例:
try:
9/0
except ZeroDivisionError as e:
raise
给出输出:
ZeroDivisionError: division by zero
鉴于:
try:
9/0
except ZeroDivisionError as e:
raise RuntimeError('I think the server is down') from e
此代码给出输出:
RuntimeError: I think the server is down
所以这是一种避免一个错误并引发另一个错误的方法。
为什么需要这样:
假设您有一个搜索文本文件的程序,并将某个数字除以它找到的文本文件的数量。如果找不到文件,它将尝试:some_number/num_files
,即 some_number/0
,它会给出 ZeroDivisionError
。在这种情况下,您可能想要 raise FileNotFoundError
。在这种情况下,您可以使用:raise FileNotFoundError('There are no text files in the specified folder.')
.
socket.timeout
是 OSError
的子类。无论出于何种原因,此代码的作者希望 client
在这种情况下提出 RuntimeError
。
这是一种常见的做法。一个包可能会在其代码的深处处理一堆不同类型的错误。但是这些例外与模块的用户有多相关——尤其是当包本身可能随时间变化时?将这些异常聚合成一个较小的、记录在案的异常集是有意义的。用户不需要捕获并弄清楚如何处理数十个含义不是很清楚的异常,该包可以完成繁重的工作并传回一组更友好的错误。
假设这个程序包有几种不同的方法从服务器获取数据,或者有几种不同的方法可以检测到已关闭的服务器。用户不关心这段代码是否超时,或者是否以其他方式检测到。可以想象分发服务器地址的中间件意识到有 none 可用。此代码中的“错误”是未记录详细错误,因此任何人都无法弄清楚发生了什么。
当然这只是猜测。我认为在您正在阅读的书中,它是有道理的。这是演示聚合异常的常见做法的演示代码。
我正在尝试从 Python 一本书中理解这段代码。
def client(hostname, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.connect((hostname, port))
print('Client socket name is {}'.format(sock.getsockname()))
delay = 0.1 # seconds
text = 'This is another message'
data = text.encode('ascii')
while True:
sock.send(data)
print('Waiting up to {} seconds for a reply'.format(delay))
sock.settimeout(delay)
try:
data = sock.recv(MAX_BYTES)
except socket.timeout as exc:
delay *= 2 # wait even longer for the next request
if delay > 2.0:
raise RuntimeError('I think the server is down') from exc
else:
break # we are done, and can stop looping
print('The server says {!r}'.format(data.decode('ascii')))
这一行:
raise RuntimeError('I think the server is down') from exc
我知道“raise”可以引发异常,而“exc”包含异常。但我不明白为什么我们需要“RuntimeError('I think the server is down')”。让我们的代码有这一行而不是只有“raise”语句有什么意义。
简而言之:
两者的输出不同:
raise
给出这个输出:
RuntimeError: No active exception to reraise #or whatever exception is active
鉴于:
raise RuntimeError('I think the server is down')
给出:
RuntimeError: I think the server is down
在后者中,您指定了一个运行时错误,而在第一个中,您只是 运行 来自异常的错误。
附加示例:
为了进一步解释,请考虑以下示例:
try:
9/0
except ZeroDivisionError as e:
raise
给出输出:
ZeroDivisionError: division by zero
鉴于:
try:
9/0
except ZeroDivisionError as e:
raise RuntimeError('I think the server is down') from e
此代码给出输出:
RuntimeError: I think the server is down
所以这是一种避免一个错误并引发另一个错误的方法。
为什么需要这样:
假设您有一个搜索文本文件的程序,并将某个数字除以它找到的文本文件的数量。如果找不到文件,它将尝试:some_number/num_files
,即 some_number/0
,它会给出 ZeroDivisionError
。在这种情况下,您可能想要 raise FileNotFoundError
。在这种情况下,您可以使用:raise FileNotFoundError('There are no text files in the specified folder.')
.
socket.timeout
是 OSError
的子类。无论出于何种原因,此代码的作者希望 client
在这种情况下提出 RuntimeError
。
这是一种常见的做法。一个包可能会在其代码的深处处理一堆不同类型的错误。但是这些例外与模块的用户有多相关——尤其是当包本身可能随时间变化时?将这些异常聚合成一个较小的、记录在案的异常集是有意义的。用户不需要捕获并弄清楚如何处理数十个含义不是很清楚的异常,该包可以完成繁重的工作并传回一组更友好的错误。
假设这个程序包有几种不同的方法从服务器获取数据,或者有几种不同的方法可以检测到已关闭的服务器。用户不关心这段代码是否超时,或者是否以其他方式检测到。可以想象分发服务器地址的中间件意识到有 none 可用。此代码中的“错误”是未记录详细错误,因此任何人都无法弄清楚发生了什么。
当然这只是猜测。我认为在您正在阅读的书中,它是有道理的。这是演示聚合异常的常见做法的演示代码。