首頁  >  文章  >  後端開發  >  Python腳本的調試和分析(程式碼範例)

Python腳本的調試和分析(程式碼範例)

不言
不言轉載
2019-04-11 13:08:353837瀏覽

本篇文章帶給大家的內容是關於Python腳本的調試和分析(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

調試和分析在Python開發中發揮重要作用 。調試器可幫助程式設計師分析完整的程式碼。偵錯器設定斷點,而分析器運行我們的程式碼並向我們提供執行時間的詳細信息,分析器將識別程式中的瓶頸。

Python調試技術

調試是一個解決程式碼中出現的問題並阻止軟體正常運作的過程。在Python中,調試非常簡單。 Python調試器設定條件斷點並一次調試一行原始碼。我們將使用pdb Python標準庫中的模組來調試我們的Python腳本  。

為了更好地調試Python程序,可以使用各種技術。我們將討論Python調試的四種技術:

  • print() 聲明:這是了解發生了什麼的最簡單方法,因此您可以檢查已執行的內容。
  • logging:這就像一個print聲明,但有更多的上下文訊息,所以你可以完全理解它。
  • pdb debugger:這是一種常用的偵錯技術。使用的優點pdb是您可以pdb從命令列,解釋器和程式中使用。
  • IDE偵錯器:IDE具有整合偵錯器。它允許開發人員執行他們的程式碼,然後開發人員可以在程式執行時進行檢查。

錯誤處理(異常處理)

在本節中,我們將學習Python如何處理例外狀況。例外是程式執行期間​​發生的錯誤。每當發生任何錯誤時,Python都會產生一個異常,該異常將使用try ... except區塊進行處理。程式無法處理某些異常,因此會導致錯誤訊息。現在,我們將看到一些異常範例。

在終端機中,啟動  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 ZeropisionError: pision 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 要捕獲的腳本ZeropisionError在腳本中編寫以下程式碼:

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("pision by zero is not possible")
 
print("Out of try...except block")

如下所示執行腳本,您將獲得以下輸出:

student@ubuntu:~$ python3 exception_example.py
The value of c is:  92
pision by zero is not possible
Out of try...except block

偵錯器工具

Python支援許多偵錯工具:

  • winpdb
  • pydev
  • #pydb
  • pdb
  • gdb
  • #pyDebug

在本節中,我們將學習pdb Python偵錯器。 pdbmodule是Python標準函式庫的一部分,始終可供使用。

pdb偵錯器

該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腳本中

前兩種技術將在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模块

如前所述,分析意味着测量程序的执行时间。我们将使用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

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程序运行得更快,例如:

  • 描述您的代码,以便识别瓶颈
  • 使用内置函数和库,因此解释器不需要执行循环
  • 避免使用全局变量,因为Python在访问全局变量时非常慢
  • 使用现有包

以上是Python腳本的調試和分析(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除