Linux中國

Python 3.3 為改進代碼中的異常處理所做的工作

這是 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: &apos;stuff&apos;

在處理上述異常的過程中,發生了另一個異常:

    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: (&apos;invalid data&apos;, &apos;stuff&apos;)

如果你使用 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: (&apos;invalid data&apos;, &apos;stuff&apos;)

歡迎來到 2012 年

儘管 Python 3.3 在十年前就已經發布了,但它的許多功能仍然很酷,而且沒有得到充分利用。如果你還沒有,就把它們添加到你的工具箱中吧。

via: https://opensource.com/article/21/5/python-33

作者:Moshe Zadka 選題:lujun9972 譯者:wxy 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國