Python 3.3 为改进代码中的异常处理所做的工作

发表于:2021-6-03 09:33

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:Moshe Zadka    来源:Linux中国

  探索异常处理和其他未被充分利用但仍然有用的 Python 特性。
  这是 Python 3.x 首发特性系列文章的第四篇。Python 3.3 于 2012 年首次发布,尽管它已经发布了很长时间,但它引入的许多特性都没有得到充分利用,而且相当酷。下面是其中的三个。
  yield from
  yield 关键字使 Python 更加强大。可以预见的是,人们都开始使用它来创建整个迭代器的生态系统。itertools 模块和 more-itertools PyPI 包就是其中两个例子。
  有时,一个新的生成器会想要使用一个现有的生成器。作为一个简单的(尽管有点故意设计)的例子,设想你想枚举所有的自然数对。
  一种方法是按照“自然数对的和,自然数对的第一项”的顺序生成所有的自然数对。用 yield from 来实现这个方法是很自然的。
  yield from <x> 关键字是以下的简称:
  for item in x:
      yield item
  import itertools
   
  def pairs():
      for n in itertools.count():
          yield from ((i, n-i) for i in range(n+1))
  list(itertools.islice(pairs(), 6))
      [(0, 0), (0, 1), (1, 0), (0, 2), (1, 1), (2, 0)]
  隐式命名空间包
  假设有一个叫 Parasol 的虚构公司,它制造了一堆东西。它的大部分内部软件都是用 Python 编写的。虽然 Parasol 已经开源了它的一些代码,但其中一些代码对于开源来说过于专有或专业。
  该公司使用内部 DevPI 服务器来管理内部软件包。对于 Parasol 的每个 Python 程序员来说,在 PyPI 上找一个未使用的名字是没有意义的,所以所有的内部包都被称为 parasol.<business division>.<project>。遵守最佳实践,开发人员希望包的名字能反映出这个命名系统。
  这一点很重要!如果 parasol.accounting.numeric_tricks 包安装了一个名为 numeric_tricks 的顶层模块,这意味着依赖这个包的人将无法使用名为 numeric_tricks 的 PyPI 包,不管它写的有多好。
  然而,这给开发者留下了一个两难的选择:哪个包拥有 parasol/__init__.py 文件?从 Python 3.3 开始,最好的解决办法是把 parasol,可能还有 parasol.accounting,变成没有 __init__.py 文件的 命名空间包。
  抑制异常的上下文
  有时,在从异常中恢复的过程中出现的异常是一个问题,有上下文来跟踪它是很有用的。然而,有时却不是这样:异常已经被处理了,而新的情况是一个不同的错误状况。
  例如,想象一下,在字典中查找一个键失败后,如果不能分析它,则希望失败并返回 ValueError()。
  import time
   
  def expensive_analysis(data):
      time.sleep(10)
      if data[0:1] == ">":
          return data[1:]
      return None
  这个函数需要很长的时间,所以当你使用它时,想要对结果进行缓存:
  cache = {}
   
  def last_letter_analyzed(data):
      try:
          analyzed = cache[data]
      except KeyError:
          analyzed = expensive_analysis(data)
          if analyzed is None:
              raise ValueError("invalid data", data)
          cached[data] = analyzed
      return analyzed[-1]
  不幸的是,当出现缓存没有命中时,回溯看起来很难看:
  last_letter_analyzed("stuff")
      ---------------------------------------------------------------------------
   
      KeyError                                  Traceback (most recent call last)
   
      <ipython-input-16-a525ae35267b> in last_letter_analyzed(data)
            4     try:
      ----> 5         analyzed = cache[data]
            6     except KeyError:
   
   
      KeyError: 'stuff'
  在处理上述异常的过程中,发生了另一个异常:
      ValueError                                Traceback (most recent call last)
   
      <ipython-input-17-40dab921f9a9> in <module>
      ----> 1 last_letter_analyzed("stuff")
     
   
      <ipython-input-16-a525ae35267b> in last_letter_analyzed(data)
            7         analyzed = expensive_analysis(data)
            8         if analyzed is None:
      ----> 9             raise ValueError("invalid data", data)
           10         cached[data] = analyzed
           11     return analyzed[-1]
   
   
      ValueError: ('invalid data', 'stuff')
  如果你使用 raise ... from None,你可以得到更多可读的回溯:
  def last_letter_analyzed(data):
      try:
          analyzed = cache[data]
      except KeyError:
          analyzed = expensive_analysis(data)
          if analyzed is None:
              raise ValueError("invalid data", data) from None
          cached[data] = analyzed
      return analyzed[-1]
  last_letter_analyzed("stuff")
      ---------------------------------------------------------------------------
   
      ValueError                                Traceback (most recent call last)
   
      <ipython-input-21-40dab921f9a9> in <module>
      ----> 1 last_letter_analyzed("stuff")
     
   
      <ipython-input-20-5691e33edfbc> in last_letter_analyzed(data)
            5         analyzed = expensive_analysis(data)
            6         if analyzed is None:
      ----> 7             raise ValueError("invalid data", data) from None
            8         cached[data] = analyzed
            9     return analyzed[-1]
   
   
      ValueError: ('invalid data', 'stuff')

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号