Python 開發模式

3.7 版本新增。

Python 開發模式引入了額外的執行時檢查,這些檢查的開銷太大,預設情況下不啟用。如果程式碼正確,它不應該比預設情況更冗長;只有在檢測到問題時才會發出新的警告。

可以使用 -X dev 命令列選項啟用它,或者將 PYTHONDEVMODE 環境變數設定為 1

另請參閱 Python 除錯版本

Python 開發模式的效果

啟用 Python 開發模式類似於以下命令,但具有下面描述的附加效果

PYTHONMALLOC=debug PYTHONASYNCIODEBUG=1 python -W default -X faulthandler

Python 開發模式的效果

預設情況下,Python 開發模式不會啟用 tracemalloc 模組,因為開銷成本(對效能和記憶體)會太大。啟用 tracemalloc 模組可以提供有關某些錯誤的來源的附加資訊。例如,ResourceWarning 會記錄資源分配的回溯,而緩衝區溢位錯誤會記錄記憶體塊分配的回溯。

Python 開發模式不會阻止 -O 命令列選項刪除 assert 語句,也不會阻止將 __debug__ 設定為 False

Python 開發模式只能在 Python 啟動時啟用。其值可以從 sys.flags.dev_mode 讀取。

在 3.8 版本中更改: io.IOBase 解構函式現在記錄 close() 異常。

在 3.9 版本中更改: 現在會檢查字串編碼和解碼操作的 encodingerrors 引數。

ResourceWarning 示例

一個指令碼的示例,該指令碼計算命令列中指定的文字檔案的行數

import sys

def main():
    fp = open(sys.argv[1])
    nlines = len(fp.readlines())
    print(nlines)
    # The file is closed implicitly

if __name__ == "__main__":
    main()

該指令碼沒有顯式關閉檔案。預設情況下,Python 不會發出任何警告。使用 README.txt 的示例,它有 269 行

$ python script.py README.txt
269

啟用 Python 開發模式會顯示 ResourceWarning 警告

$ python -X dev script.py README.txt
269
script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='README.rst' mode='r' encoding='UTF-8'>
  main()
ResourceWarning: Enable tracemalloc to get the object allocation traceback

此外,啟用 tracemalloc 會顯示開啟檔案的行

$ python -X dev -X tracemalloc=5 script.py README.rst
269
script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='README.rst' mode='r' encoding='UTF-8'>
  main()
Object allocated at (most recent call last):
  File "script.py", lineno 10
    main()
  File "script.py", lineno 4
    fp = open(sys.argv[1])

修復方法是顯式關閉檔案。使用上下文管理器的示例

def main():
    # Close the file explicitly when exiting the with block
    with open(sys.argv[1]) as fp:
        nlines = len(fp.readlines())
    print(nlines)

不顯式關閉資源可能會使資源開啟的時間比預期的長得多;它可能會在退出 Python 時引起嚴重問題。這在 CPython 中是不好的,但在 PyPy 中更糟糕。顯式關閉資源可以使應用程式更具確定性和更可靠性。

錯誤的檔案描述符示例

顯示自身第一行的指令碼

import os

def main():
    fp = open(__file__)
    firstline = fp.readline()
    print(firstline.rstrip())
    os.close(fp.fileno())
    # The file is closed implicitly

main()

預設情況下,Python 不會發出任何警告

$ python script.py
import os

Python 開發模式會顯示 ResourceWarning,並在最終確定檔案物件時記錄 “錯誤的檔案描述符” 錯誤

$ python -X dev script.py
import os
script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='script.py' mode='r' encoding='UTF-8'>
  main()
ResourceWarning: Enable tracemalloc to get the object allocation traceback
Exception ignored in: <_io.TextIOWrapper name='script.py' mode='r' encoding='UTF-8'>
Traceback (most recent call last):
  File "script.py", line 10, in <module>
    main()
OSError: [Errno 9] Bad file descriptor

os.close(fp.fileno()) 關閉檔案描述符。當檔案物件 finalizer 再次嘗試關閉檔案描述符時,它會因 Bad file descriptor 錯誤而失敗。檔案描述符只能關閉一次。在最壞的情況下,關閉兩次可能會導致崩潰(例如,請參閱 bpo-18748)。

修復方法是刪除 os.close(fp.fileno()) 行,或使用 closefd=False 開啟檔案。