ホームページ  >  記事  >  バックエンド開発  >  Python スクリプトのデバッグと分析 (コード例)

Python スクリプトのデバッグと分析 (コード例)

不言
不言転載
2019-04-11 13:08:353914ブラウズ

この記事の内容は、Python スクリプト (コード例) のデバッグと分析に関するものであり、一定の参考価値があります。必要な友人が参照することができます。お役に立てれば幸いです。

デバッグとプロファイリングは、Python 開発において重要な役割を果たします。デバッガは、プログラマーが完全なコードを分析するのに役立ちます。プロファイラーがコードを実行している間、デバッガーはブレークポイントを設定し、実行時間の詳細を提供し、プログラム内のボトルネックを特定します。

Python デバッグ テクノロジ

デバッグは、コード内で発生し、ソフトウェアの適切な機能を妨げる問題のトラブルシューティングを行うプロセスです。 Python ではデバッグが非常に簡単です。 Python デバッガーは条件付きブレークポイントを設定し、ソース コードを一度に 1 行ずつデバッグします。 Python 標準ライブラリの pdb モジュールを使用して、Python スクリプトをデバッグします。

Python プログラムをより適切にデバッグするには、さまざまなテクニックを使用できます。 Python デバッグのための 4 つのテクニックについて説明します。

  • print() ステートメント: これは何が起こっているかを理解する最も簡単な方法であり、実行された内容を検査できます。
  • logging: これは print ステートメントに似ていますが、完全に理解できるように、より多くのコンテキスト情報が含まれています。
  • pdb デバッガ : これは、一般的に使用されるデバッグ手法です。 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...excel ブロッ​​クを見てみましょう。 try ブロックでは、例外を生成する可能性のあるコードを記述します。例外ブロックには、この例外の解決策を記述します。

try...exc 構文は次のとおりです。

try:
            statement(s)
except:
            statement(s)

try ブロックには複数の else ステートメントを含めることができます。また、excel キーワードの後に​​例外名を入力することで、特定の例外を処理することもできます。特定の例外を処理するための構文は次のとおりです。

try:
            statement(s)
except exception_name:
            statement(s)

ZeropisionError をキャッチするための例外_example.py スクリプトを作成します。 次のコードをスクリプトに記述します:

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 デバッガーの使用方法を学びます。このデバッガを使用するには、次の 3 つの方法があります。

·インタープリタで使用する

·コマンド ラインから使用する

·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)

デバッグを続行するには、(Pdb) プロンプトの後に continue と入力し、Enter キーを押します。ここで使用できるオプションを知りたい場合は、(Pdb) プロンプトの後に Tab キーを 2 回押します。

「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 スクリプト内

最初の 2 つの手法は、Python プログラムの先頭でデバッガーを起動します。ただし、この 3 番目の手法は、長時間実行されるプロセスに最適です。スクリプトでデバッガーを開始するには、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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。