- 來源 | 願碼(ChainDesk.CN)內容編輯
- 願碼Slogan | 鏈接每一個程序員的故事
- 網站 | http://chaindesk.cn
- 願碼願景 | 打造全學科IT系統免費課程,助力小白用戶、初級工程師0成本免費系統學習、低成本進階,幫助BAT一線資深工程師成長並利用自身優點創造睡後收入。
- 官方公衆號 | 願碼 | 願碼服務號 | 區塊鏈部落
- 免費加入願碼全思惟工程師社羣 | 任一公衆號回覆「願碼」兩個字獲取入羣二維碼
本文閱讀時長:11minpython
調試和分析在Python開發中發揮重要做用 。調試器可幫助程序員分析完整的代碼。調試器設置斷點,而分析器運行咱們的代碼並向咱們提供執行時間的詳細信息,分析器將識別程序中的瓶頸。linux
調試是一個解決代碼中出現的問題並阻止軟件正常運行的過程。在Python中,調試很是簡單。Python調試器設置條件斷點並一次調試一行源代碼。咱們將使用pdb Python標準庫中的模塊調試咱們的Python腳本 。程序員
爲了更好地調試Python程序,可使用各類技術。咱們將討論Python調試的四種技術:ubuntu
在本節中,咱們將學習Python如何處理異常。例外是程序執行期間發生的錯誤。每當發生任何錯誤時,Python都會生成一個異常,該異常將使用try ... except塊進行處理。程序沒法處理某些異常,所以會致使錯誤消息。如今,咱們將看到一些異常示例。app
在終端中,啓動 python3交互式控制檯,咱們將看到一些異常示例:函數
student@ubuntu:~$ python3 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> >>> 50 / 0 Traceback (most recent call last): File "", line 1, in ZeroDivisionError: division by zero >>> >>> 6 + abc*5 Traceback (most recent call last): File "", line 1, in NameError: name 'abc' is not defined >>> >>> 'abc' + 2 Traceback (most recent call last): File "", line 1, in TypeError: Can't convert 'int' object to str implicitly >>> >>> import abcd Traceback (most recent call last): File "", line 1, in ImportError: No module named 'abcd' >>>
這些是例外的一些例子。如今,咱們將看到咱們如何處理異常。工具
每當Python程序中發生錯誤時,都會引起異常。咱們還可使用raise關鍵字強制引起異常。學習
如今咱們將看到一個try…except處理異常的塊。在try塊中,咱們將編寫可能生成異常的代碼。在except塊中,咱們將爲該異常編寫解決方案。區塊鏈
語法 try…except以下:測試
try: statement(s) except: statement(s)
一個try塊能夠有多個except語句。咱們也能夠經過在except關鍵字後面輸入例外名稱來處理特定的例外。處理特定異常的語法以下:
try: statement(s) except exception_name: statement(s)
咱們將建立一個exception_example.py 要捕獲的腳本ZeroDivisionError。在腳本中編寫如下代碼:
a = 35 b = 57 try: c = a + b print("The value of c is: ", c) d = b / 0 print("The value of d is: ", d) except: print("Division by zero is not possible") print("Out of try...except block")
按以下所示運行腳本,您將得到如下輸出:
student@ubuntu:~$ python3 exception_example.py The value of c is: 92 Division by zero is not possible Out of try...except block
Python支持許多調試工具:
在本節中,咱們將學習pdb Python調試器。pdbmodule是Python標準庫的一部分,始終可供使用。
該pdb模塊用於調試Python程序。Python程序使用pdb交互式源代碼調試器來調試程序。pdb設置斷點並檢查堆棧幀,並列出源代碼。
如今咱們將瞭解如何使用pdb調試器。有三種方法可使用此調試器:
· 在解釋器中
· 從命令行
· 在Python腳本中
咱們將建立一個pdb_example.py腳本並在該腳本中添加如下內容:
class Student: def __init__(self, std): self.count = std def print_std(self): for i in range(self.count): print(i) return if __name__ == '__main__': Student(5).print_std()
以此腳本爲例學習Python調試,咱們將看到如何詳細啓動調試器。
要從Python交互式控制檯啓動調試器,咱們使用run()或runeval()。
啓動python3交互式控制檯。運行如下命令以啓動控制檯:
$ python3
導入咱們的 pdb_example腳本名稱和pdb模塊。如今,咱們將使用run()而且咱們將字符串表達式做爲參數傳遞給run()Python解釋器自己:
student@ubuntu:~$ python3 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> >>> import pdb_example >>> import pdb >>> pdb.run('pdb_example.Student(5).print_std()') > (1)() (Pdb)
要繼續調試,請continue在(Pdb)提示符後輸入並按Enter鍵。若是你想知道咱們能夠在這裏使用的選項,那麼在(Pdb)提示後按兩次Tab 鍵。
如今,輸入後continue,咱們將得到以下輸出:
student@ubuntu:~$ python3 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> >>> import pdb_example >>> import pdb >>> pdb.run('pdb_example.Student(5).print_std()') > (1)() (Pdb) continue 0 1 2 3 4 >>>
運行調試器的最簡單,最直接的方法是從命令行。咱們的程序將做爲調試器的輸入。您能夠從命令行使用調試器,以下所示:
$ python3 -m pdb pdb_example.py
從命令行運行調試器時,將加載源代碼,它將中止在找到的第一行執行。輸入continue以繼續調試。這是輸出:
student@ubuntu:~$ python3 -m pdb pdb_example.py > /home/student/pdb_example.py(1)() -> class Student: (Pdb) continue 0 1 2 3 4 The program finished and will be restarted > /home/student/pdb_example.py(1)() -> class Student: (Pdb)
前兩種技術將在Python程序開始時啓動調試器。但這第三種技術最適合長期運行的流程。要在腳本中啓動調試器,請使用set_trace()。
如今,修改您的pdb_example.py 文件,以下所示:
import pdb class Student: def __init__(self, std): self.count = std def print_std(self): for i in range(self.count): pdb.set_trace() print(i) return if __name__ == '__main__': Student(5).print_std()
如今,按以下方式運行程序:
student@ubuntu:~$ python3 pdb_example.py > /home/student/pdb_example.py(10)print_std() -> print(i) (Pdb) continue 0 > /home/student/pdb_example.py(9)print_std() -> pdb.set_trace() (Pdb)
set_trace() 是一個Python函數,所以您能夠在程序中的任何位置調用它。
所以,這些是啓動調試器的三種方式。
在本節中,咱們將看到跟蹤模塊。跟蹤模塊有助於跟蹤程序執行。所以,每當您的Python程序崩潰時,咱們均可以理解崩潰的位置。咱們能夠經過將跟蹤模塊導入您的腳本以及命令行來使用它。
如今,咱們將建立一個名爲腳本trace_example.py並在腳本中編寫如下內容:
class Student: def __init__(self, std): self.count = std def go(self): for i in range(self.count): print(i) return if __name__ == '__main__': Student(5).go()
輸出以下:
student@ubuntu:~$ python3 -m trace --trace trace_example.py --- modulename: trace_example, funcname: trace_example.py(1): class Student: --- modulename: trace_example, funcname: Student trace_example.py(1): class Student: trace_example.py(2): def __init__(self, std): trace_example.py(5): def go(self): trace_example.py(10): if __name__ == '__main__': trace_example.py(11): Student(5).go() --- modulename: trace_example, funcname: init trace_example.py(3): self.count = std --- modulename: trace_example, funcname: go trace_example.py(6): for i in range(self.count): trace_example.py(7): print(i) 0 trace_example.py(6): for i in range(self.count): trace_example.py(7): print(i) 1 trace_example.py(6): for i in range(self.count): trace_example.py(7): print(i) 2 trace_example.py(6): for i in range(self.count): trace_example.py(7): print(i) 3 trace_example.py(6): for i in range(self.count): trace_example.py(7): print(i) 4
所以,經過trace --trace在命令行使用,開發人員能夠逐行跟蹤程序。所以,只要程序崩潰,開發人員就會知道崩潰的實例。
分析Python程序意味着測量程序的執行時間。它衡量每一個功能所花費的時間。Python的cProfile模塊用於分析Python程序。
如前所述,分析意味着測量程序的執行時間。咱們將使用cProfile Python模塊來分析程序。
如今,咱們將編寫一個 cprof_example.py 腳本並在其中編寫如下代碼:
mul_value = 0 def mul_numbers( num1, num2 ): mul_value = num1 * num2; print ("Local Value: ", mul_value) return mul_value mul_numbers( 58, 77 ) print ("Global Value: ", mul_value)
運行程序,您將看到以下輸出:
student@ubuntu:~$ python3 -m cProfile cprof_example.py Local Value: 4466 Global Value: 0 6 function calls in 0.000 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 0.000 0.000 cprof_example.py:1() 1 0.000 0.000 0.000 0.000 cprof_example.py:2(mul_numbers) 1 0.000 0.000 0.000 0.000 {built-in method builtins.exec} 2 0.000 0.000 0.000 0.000 {built-in method builtins.print} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
所以,使用時cProfile,全部被調用的函數都將打印出每一個函數所花費的時間。如今,咱們將看到這些列標題的含義:
· ncalls: 通話次數
· tottime: 在給定函數中花費的總時間
· percall:商數tottime除以ncalls
· cumtime:在此和全部方面花費的累計時間 subfunctions
· percall:cumtime除以原始調用的商數
· filename:lineno(function):提供每一個功能的相應數據
timeit是一個Python模塊,用於計算Python腳本的一小部分。您能夠從命令行調用timeit,也能夠將timeit模塊導入到腳本中。咱們將編寫一個腳原本計算一段代碼。建立一個timeit_example.py腳本並將如下內容寫入其中:
import timeit prg_setup = "from math import sqrt" prg_code = ''' def timeit_example(): list1 = [] for x in range(50): list1.append(sqrt(x)) ''' # timeit statement print(timeit.timeit(setup = prg_setup, stmt = prg_code, number = 10000))
使用timeit,咱們能夠決定咱們要測量的代碼片斷。所以,咱們能夠輕鬆定義設置代碼以及咱們要單獨執行測試的代碼段。主代碼運行100萬次,這是默認時間,而設置代碼只運行一次。
有多種方法可使Python程序運行得更快,例如: