成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Python Debug(調(diào)試)的終極指南

開發(fā) 后端
很多人使用一堆print語句來查看代碼中發(fā)生了什么。這種方法遠不是理想的,有更好的方法可以找出代碼的錯誤所在,本文將探討其中一些問題和應(yīng)對方法。

即使您編寫了清晰可讀的代碼,即使您是非常有經(jīng)驗的開發(fā)人員,奇怪的bug也不可避免地會出現(xiàn),您將需要以某種方式調(diào)試它們。很多人使用一堆print語句來查看代碼中發(fā)生了什么。這種方法遠不是理想的,有更好的方法可以找出代碼的錯誤所在,本文將探討其中一些問題和應(yīng)對方法。

日志是必須的

如果在編寫應(yīng)用程序時沒有設(shè)置日志記錄,那么您最終會后悔的。應(yīng)用程序中沒有任何日志會使故障排除變得非常困難。幸運的是,在Python中,建立基本的日志程序非常簡單:

  1. import logging 
  2. logging.basicConfig( 
  3.     filename='application.log'
  4.     level=logging.WARNING, 
  5.     format'[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s'
  6.     datefmt='%H:%M:%S' 
  7.  
  8. logging.error("Some serious error occurred.") 
  9. logging.warning('Function you are using is deprecated.') 

這就是所有你需要開始寫日志的文件,它看起來像這樣,你可以找到文件的路徑使用logger . getloggerclass ().root.handlers[0].baseFilename):

  1. [12:52:35] {<stdin>:1} ERROR - Some serious error occurred. 
  2. [12:52:35] {<stdin>:1} WARNING - Function you are using is deprecated. 

這種設(shè)置看起來似乎已經(jīng)足夠好了(通常情況下也是如此),但是擁有配置良好、格式化、可讀的日志可以使您的工作變得更加容易。改進和擴展配置的一種方法是使用被logger讀取的.ini或.yaml文件。舉個例子,你可以在配置中做什么:

  1. version: 1 
  2. disable_existing_loggers: true 
  3.  
  4. formatters: 
  5.   standard: 
  6.     format: "[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s" 
  7.     datefmt: '%H:%M:%S' 
  8.  
  9. handlers: 
  10.   console:  # handler which will log into stdout 
  11.     class: logging.StreamHandler 
  12.     level: DEBUG 
  13.     formatter: standard  # Use formatter defined above 
  14.     stream: ext://sys.stdout 
  15.   file:  # handler which will log into file 
  16.     class: logging.handlers.RotatingFileHandler 
  17.     level: WARNING 
  18.     formatter: standard  # Use formatter defined above 
  19.     filename: /tmp/warnings.log 
  20.     maxBytes: 10485760 # 10MB 
  21.     backupCount: 10 
  22.     encoding: utf8 
  23.  
  24. root:  # Loggers are organized in hierarchy - this is the root logger config 
  25.   level: ERROR 
  26.   handlers: [console, file]  # Attaches both handler defined above 
  27.  
  28. loggers:  # Defines descendants of root logger 
  29.   mymodule:  # Logger for "mymodule" 
  30.     level: INFO 
  31.     handlers: [file]  # Will only use "file" handler defined above 
  32.     propagate: no  # Will not propagate logs to "root" logger 

在python代碼中使用這種擴展的配置將很難導(dǎo)航、編輯和維護。將內(nèi)容保存在YAML文件中,可以通過非常特定的設(shè)置(如上面的設(shè)置)更容易地設(shè)置和調(diào)整多個日志記錄器。

在文件中有了配置,意味著我們需要加載。最簡單的方法做與YAML文件:

  1. import yaml 
  2. from logging import config 
  3.  
  4. with open("config.yaml", 'rt') as f: 
  5.     config_data = yaml.safe_load(f.read()) 
  6.     config.dictConfig(config_data) 

Python logger實際上并不直接支持YAML文件,但是它支持字典配置,可以使用YAML .safe_load輕松地從YAML創(chuàng)建字典配置。如果您更傾向于使用舊的.ini文件,那么我只想指出,對于新應(yīng)用程序,根據(jù)文檔,推薦使用字典configs。

__repr__ 可讀的日志

對代碼進行簡單的改進,使其更具可調(diào)試性,可以在類中添加__repr__方法。如果你不熟悉這個方法-它所做的只是返回一個類實例的字符串表示。使用__repr__方法的最佳實踐是輸出可用于重新創(chuàng)建實例的文本。例如:

  1. class Circle: 
  2.     def __init__(self, x, y, radius): 
  3.         self.x = x 
  4.         self.y = y 
  5.         self.radius = radius 
  6.  
  7.     def __repr__(self): 
  8.         return f"Rectangle({self.x}, {self.y}, {self.radius})" 
  9.  
  10. ... 
  11. c = Circle(100, 80, 30) 
  12. repr(c) 
  13. # Circle(100, 80, 30) 

除了__repr__,在調(diào)用print(實例)時,執(zhí)行__str__方法也是一個好主意。有了這兩種方法,你可以通過打印你的變量得到很多信息。

針對字典的__missing__方法

如果出于某種原因需要實現(xiàn)自定義dictionary類,那么在嘗試訪問一些實際上不存在的密鑰時,您可能會遇到一些由keyerror引起的錯誤。為了避免在代碼中到處查看丟失了哪個鍵(key),你可以實現(xiàn)特殊的__miss__方法,每次KeyError被提出時調(diào)用。

  1. class MyDict(dict): 
  2.     def __missing__(self, key): 
  3.         message = f'{key} not present in the dictionary!' 
  4.         logging.warning(message) 
  5.         return message  # Or raise some error instead 

上面的實現(xiàn)非常簡單,只返回和記錄丟失鍵的消息,但是您還可以記錄其他有價值的信息,以便了解代碼中出現(xiàn)了什么問題。

調(diào)試崩潰的應(yīng)用程序

如果您的應(yīng)用程序在您有機會了解其中發(fā)生了什么之前就崩潰了,那么您可能會發(fā)現(xiàn)這個技巧非常有用。

使用-i參數(shù)運行應(yīng)用程序(python3 -i app.py)會導(dǎo)致程序一退出就啟動交互式shell。此時,您可以檢查變量和函數(shù)。

如果這還不夠好,您可以帶一個更強大的工具 - pdb - Python調(diào)試器。pdb有很多特性,可以單獨寫一篇文章來說明。但這里有一個例子和最重要的部分的綱要。讓我們先看看崩潰腳本:

  1. # crashing_app.py 
  2. SOME_VAR = 42 
  3.  
  4. class SomeError(Exception): 
  5.     pass 
  6.  
  7. def func(): 
  8.     raise SomeError("Something went wrong...") 
  9.  
  10. func() 

現(xiàn)在,如果我們用-i參數(shù)運行它,我們就有機會調(diào)試它:

  1. # Run crashing application 
  2. ~ $ python3 -i crashing_app.py 
  3. Traceback (most recent call last): 
  4.   File "crashing_app.py", line 9, in <module> 
  5.     func() 
  6.   File "crashing_app.py", line 7, in func 
  7.     raise SomeError("Something went wrong...") 
  8. __main__.SomeError: Something went wrong... 
  9. >>> # We are interactive shell 
  10. >>> import pdb 
  11. >>> pdb.pm()  # start Post-Mortem debugger 
  12. > .../crashing_app.py(7)func() 
  13. -> raise SomeError("Something went wrong...") 
  14. (Pdb) # Now we are in debugger and can poke around and run some commands: 
  15. (Pdb) p SOME_VAR  # Print value of variable 
  16. 42 
  17. (Pdb) l  # List surrounding code we are working with 
  18.   2      
  19.   3     class SomeError(Exception): 
  20.   4         pass 
  21.   5      
  22.   6     def func(): 
  23.   7  ->     raise SomeError("Something went wrong...") 
  24.   8      
  25.   9     func() 
  26. [EOF] 
  27. (Pdb)  # Continue debugging... set breakpoints, step through the code, etc. 

上面的調(diào)試會話非常簡單地展示了使用pdb可以做什么。程序結(jié)束后,我們進入交互式調(diào)試會話。首先,導(dǎo)入pdb并啟動調(diào)試器。此時,我們可以使用所有pdb命令。作為上面的示例,我們使用p命令打印變量,使用l命令列出代碼。大部分時間你可能會想要設(shè)置斷點,可以與b LINE_NO和運行程序,直到斷點(c),然后繼續(xù)與年代,逐頁瀏覽功能的選擇可能與w。

堆棧跟蹤

假設(shè)您的代碼是運行在遠程服務(wù)器上的Flask或Django應(yīng)用程序,在那里您無法獲得交互式調(diào)試會話。在這種情況下,你可以使用traceback和sys包來了解你的代碼中失敗的地方:

  1. import traceback 
  2. import sys 
  3.  
  4. def func(): 
  5.     try: 
  6.         raise SomeError("Something went wrong...") 
  7.     except: 
  8.         traceback.print_exc(file=sys.stderr) 

在運行時,上面的代碼將打印引發(fā)的最后一個異常。除了打印異常,您還可以使用traceback包來打印stacktrace (traceback. print_stack())或提取原始堆棧幀,格式化它并進一步檢查它(traceback. format_list(traceback.extract_stack()))。

在調(diào)試期間重新加載模塊

有時,您可能在交互式shell中調(diào)試或試驗?zāi)承┖瘮?shù),并經(jīng)常對其進行更改。為了使運行/測試和修改的循環(huán)更容易,您可以運行importlib.reload(模塊),以避免在每次更改后重新啟動交互會話:

  1. >>> import func from module 
  2. >>> func() 
  3. "This is result..." 
  4.  
  5. # Make some changes to "func" 
  6. >>> func() 
  7. "This is result..."  # Outdated result 
  8. >>> from importlib import reload; reload(module)  # Reload "module" after changes made to "func" 
  9. >>> func() 
  10. "New result..." 

這個技巧更多的是關(guān)于效率而不是調(diào)試。能夠跳過一些不必要的步驟,使您的工作流程更快、更高效總是很好的。一般來說,不時地重新加載模塊是一個好主意,因為它可以幫助您避免調(diào)試已經(jīng)被修改了很多次的代碼。

 

責(zé)任編輯:趙寧寧 來源: 今日頭條
相關(guān)推薦

2023-05-05 17:20:04

2015-07-20 09:39:41

Java日志終極指南

2017-03-27 21:14:32

Linux日志指南

2012-08-21 06:53:00

測試軟件測試

2025-03-11 00:54:42

2023-05-23 18:31:14

Rust編程

2022-06-30 08:00:00

MySQL關(guān)系數(shù)據(jù)庫開發(fā)

2024-08-19 00:40:00

SQL數(shù)據(jù)庫

2020-06-24 12:26:28

企業(yè)網(wǎng)絡(luò)IT管理

2024-09-10 08:26:40

2015-03-05 11:28:51

Linux桌面環(huán)境終極指南

2015-11-08 14:44:48

2022-02-09 09:00:00

云計算BigQuerySnowflake

2024-07-10 09:07:09

2024-05-17 09:46:17

Python單元測試unittest模塊

2022-04-28 10:29:38

數(shù)據(jù)數(shù)據(jù)收集

2022-03-28 09:52:42

JavaScript語言

2025-01-14 00:00:00

2024-02-23 18:59:32

Python函數(shù)編程

2013-12-18 09:36:08

企業(yè)移動指南
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 狠狠躁天天躁夜夜躁婷婷老牛影视 | av网站免费在线观看 | 欧美电影在线观看网站 | 亚洲成人av一区二区 | 国产精品美女久久久久久久网站 | 日本一区二区三区在线观看 | 国产乱码高清区二区三区在线 | 亚洲一区国产 | 亚洲精品乱码久久久久久按摩观 | 亚洲视频在线观看 | 欧美日韩中文字幕在线 | 99re在线免费视频 | 欧美国产精品一区二区三区 | 国产一区二区三区四区 | 人人射人人 | 国产精品视频一区二区三区 | 国产免费播放视频 | 一本久久a久久精品亚洲 | 久久久国产精品 | av一区二区三区四区 | 欧美一级片在线看 | 久久99久久98精品免观看软件 | 91一区二区在线观看 | 久久成人国产精品 | 国产成人精品a视频一区www | 欧洲亚洲一区二区三区 | 国产精品一区二区久久久久 | 久久久国产精品 | 日日做夜夜爽毛片麻豆 | 国产精品久久久久久久久久免费看 | 欧美视频网 | 日韩视频在线观看一区二区 | 国产日韩一区二区 | 一级欧美 | 亚洲欧美一区二区三区视频 | 国产精品一区一区 | 视频一二三区 | 91精品亚洲 | 久久精品视频一区二区三区 | 久久男人 | 国产一区二区免费在线 |