您好,登錄后才能下訂單哦!
本篇內容主要講解“Python Debug調試的方法是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Python Debug調試的方法是什么”吧!
日志是必須的
如果在編寫應用程序時沒有設置日志記錄,那么您最終會后悔的。應用程序中沒有任何日志會使故障排除變得非常困難。幸運的是,在Python中,建立基本的日志程序非常簡單:
import logging logging.basicConfig( filename='application.log', level=logging.WARNING, format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', datefmt='%H:%M:%S' ) logging.error("Some serious error occurred.") logging.warning('Function you are using is deprecated.')
這就是所有你需要開始寫日志的文件,它看起來像這樣,你可以找到文件的路徑使用logger . getloggerclass ().root.handlers[0].baseFilename):
[12:52:35] {<stdin>:1} ERROR - Some serious error occurred. [12:52:35] {<stdin>:1} WARNING - Function you are using is deprecated.
這種設置看起來似乎已經足夠好了(通常情況下也是如此),但是擁有配置良好、格式化、可讀的日志可以使您的工作變得更加容易。改進和擴展配置的一種方法是使用被logger讀取的.ini或.yaml文件。舉個例子,你可以在配置中做什么:
version: 1 disable_existing_loggers: true formatters: standard: format: "[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s" datefmt: '%H:%M:%S' handlers: console: # handler which will log into stdout class: logging.StreamHandler level: DEBUG formatter: standard # Use formatter defined above stream: ext://sys.stdout file: # handler which will log into file class: logging.handlers.RotatingFileHandler level: WARNING formatter: standard # Use formatter defined above filename: /tmp/warnings.log maxBytes: 10485760 # 10MB backupCount: 10 encoding: utf8 root: # Loggers are organized in hierarchy - this is the root logger config level: ERROR handlers: [console, file] # Attaches both handler defined above loggers: # Defines descendants of root logger mymodule: # Logger for "mymodule" level: INFO handlers: [file] # Will only use "file" handler defined above propagate: no # Will not propagate logs to "root" logger
在python代碼中使用這種擴展的配置將很難導航、編輯和維護。將內容保存在YAML文件中,可以通過非常特定的設置(如上面的設置)更容易地設置和調整多個日志記錄器。
在文件中有了配置,意味著我們需要加載。最簡單的方法做與YAML文件:
import yaml from logging import config with open("config.yaml", 'rt') as f: config_data = yaml.safe_load(f.read()) config.dictConfig(config_data)
Python logger實際上并不直接支持YAML文件,但是它支持字典配置,可以使用YAML .safe_load輕松地從YAML創建字典配置。如果您更傾向于使用舊的.ini文件,那么我只想指出,對于新應用程序,根據文檔,推薦使用字典configs。
__repr__ 可讀的日志
對代碼進行簡單的改進,使其更具可調試性,可以在類中添加__repr__方法。如果你不熟悉這個方法-它所做的只是返回一個類實例的字符串表示。使用__repr__方法的最佳實踐是輸出可用于重新創建實例的文本。例如:
class Circle: def __init__(self, x, y, radius): self.x = x self.y = y self.radius = radius def __repr__(self): return f"Rectangle({self.x}, {self.y}, {self.radius})" ... c = Circle(100, 80, 30) repr(c) # Circle(100, 80, 30)
除了__repr__,在調用print(實例)時,執行__str__方法也是一個好主意。有了這兩種方法,你可以通過打印你的變量得到很多信息。
針對字典的__missing__方法
如果出于某種原因需要實現自定義dictionary類,那么在嘗試訪問一些實際上不存在的密鑰時,您可能會遇到一些由keyerror引起的錯誤。為了避免在代碼中到處查看丟失了哪個鍵(key),你可以實現特殊的__miss__方法,每次KeyError被提出時調用。
class MyDict(dict): def __missing__(self, key): message = f'{key} not present in the dictionary!' logging.warning(message) return message # Or raise some error instead
上面的實現非常簡單,只返回和記錄丟失鍵的消息,但是您還可以記錄其他有價值的信息,以便了解代碼中出現了什么問題。
調試崩潰的應用程序
如果您的應用程序在您有機會了解其中發生了什么之前就崩潰了,那么您可能會發現這個技巧非常有用。
使用-i參數運行應用程序(python3 -i app.py)會導致程序一退出就啟動交互式shell。此時,您可以檢查變量和函數。
如果這還不夠好,您可以帶一個更強大的工具 - pdb - Python調試器。pdb有很多特性,可以單獨寫一篇文章來說明。但這里有一個例子和最重要的部分的綱要。讓我們先看看崩潰腳本:
# crashing_app.py SOME_VAR = 42 class SomeError(Exception): pass def func(): raise SomeError("Something went wrong...") func()
現在,如果我們用-i參數運行它,我們就有機會調試它:
# Run crashing application ~ $ python3 -i crashing_app.py Traceback (most recent call last): File "crashing_app.py", line 9, in <module> func() File "crashing_app.py", line 7, in func raise SomeError("Something went wrong...") __main__.SomeError: Something went wrong... >>> # We are interactive shell >>> import pdb >>> pdb.pm() # start Post-Mortem debugger > .../crashing_app.py(7)func() -> raise SomeError("Something went wrong...") (Pdb) # Now we are in debugger and can poke around and run some commands: (Pdb) p SOME_VAR # Print value of variable 42 (Pdb) l # List surrounding code we are working with 2 3 class SomeError(Exception): 4 pass 5 6 def func(): 7 -> raise SomeError("Something went wrong...") 8 9 func() [EOF] (Pdb) # Continue debugging... set breakpoints, step through the code, etc.
上面的調試會話非常簡單地展示了使用pdb可以做什么。程序結束后,我們進入交互式調試會話。首先,導入pdb并啟動調試器。此時,我們可以使用所有pdb命令。作為上面的示例,我們使用p命令打印變量,使用l命令列出代碼。大部分時間你可能會想要設置斷點,可以與b LINE_NO和運行程序,直到斷點(c),然后繼續與年代,逐頁瀏覽功能的選擇可能與w。
堆棧跟蹤
假設您的代碼是運行在遠程服務器上的Flask或Django應用程序,在那里您無法獲得交互式調試會話。在這種情況下,你可以使用traceback和sys包來了解你的代碼中失敗的地方:
import traceback import sys def func(): try: raise SomeError("Something went wrong...") except: traceback.print_exc(file=sys.stderr)
在運行時,上面的代碼將打印引發的最后一個異常。除了打印異常,您還可以使用traceback包來打印stacktrace (traceback. print_stack())或提取原始堆棧幀,格式化它并進一步檢查它(traceback. format_list(traceback.extract_stack()))。
在調試期間重新加載模塊
有時,您可能在交互式shell中調試或試驗某些函數,并經常對其進行更改。為了使運行/測試和修改的循環更容易,您可以運行importlib.reload(模塊),以避免在每次更改后重新啟動交互會話:
>>> import func from module >>> func() "This is result..." # Make some changes to "func" >>> func() "This is result..." # Outdated result >>> from importlib import reload; reload(module) # Reload "module" after changes made to "func" >>> func() "New result..."
到此,相信大家對“Python Debug調試的方法是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。