python程序调试
介绍 (Introduction)
It’s nearly impossible that a program can be written once and run perfectly all the time. Bugs and debugging are part of the daily lives of programmers. Therefore, to learn some useful debugging techniques is an important task for every developer. This post will introduce six debugging techniques for Python developers.
一个程序只能编写一次并始终运行完美几乎是不可能的。 错误和调试是程序员日常生活的一部分。 因此,学习一些有用的调试技术是每个开发人员的重要任务。 这篇文章将为Python开发人员介绍六种调试技术。
1.打印并检查 (1. Print and Check)
The simplest but powerful method is to print some particular variables and check their values are as expected or not.
最简单但功能强大的方法是打印一些特定变量,并检查其值是否符合预期。
Print and check method 打印和检查方法As the above example shown, if we are not sure with a variable, we can just print and check it. After that, some modifications can be considered.
如上面的示例所示,如果不确定是否有变量,则可以打印并检查它。 之后,可以考虑进行一些修改。
The biggest disadvantage of using print
is that you have to delete it in the future. The program will be hard to read if there are print
statements everywhere and the results will also contain a lot of garbage information. No worries, we have other techniques.
使用print
的最大缺点是您将来必须删除它。 如果到处都有print
语句,该程序将难以阅读,并且结果还将包含大量垃圾信息。 不用担心,我们还有其他技术。
2.声明并检查 (2. Assert and Check)
Wherever the print
is used to assist debugging, assert
can be used instead.
无论将print
用于协助调试的任何地方,都可以使用assert
来代替。
As the example shown, Python’s build-in assert
method can raise an AssertionError
if its statement is False
.
如所示示例,如果Python的内置assert
方法的语句为False
则可以引发AssertionError
。
Python gives us more flexibility when using assert
. We can use the -0
parameter to close all the assert
statements in the program when starting the Python interpreter. After that, all the assert
methods will not work.
使用assert
时,Python为我们提供了更大的灵活性。 启动Python解释器时,我们可以使用-0
参数关闭程序中的所有assert
语句。 在那之后,所有的assert
方法将不起作用。
python -0 assert.py
# Traceback (most recent call last):
# ...
# ValueError: invalid literal for int() with base 10: 'Yang'
Although the Assert and Check method is a little flexible than the Print and Check, lots of assert
statements will also make our code a bit confusing and unreadable.
尽管Assert and Check方法比Print and Check方法灵活一些,但是许多assert
语句也会使我们的代码有些混乱和不可读。
3.使用日志记录模块 (3. Using logging Module)
Python has an important module named logging
. Replacing print
or assert
to logging methods is more professional and powerful way to debug. Actually, it is a “heavy weapon” for a Python project. Because it gives us lots of flexibility and abilities to debug, record and monitor our programs.
Python有一个名为logging
的重要模块。 将print
或assert
替换为logging方法是更专业,更强大的调试方式。 实际上,它是Python项目的“重武器”。 因为它为我们提供了调试,记录和监视程序的灵活性和能力。
For example, through simple configuration, a statement can be output to different places, such as console and files.
例如,通过简单的配置,一条语句可以输出到不同的位置,例如控制台和文件。
output logging info to a file 将日志信息输出到文件The above example shows that we can print logging messages to a file rather than console. It’s pretty useful if there is much information and inconvenient to look at them in the console. Not to mention it’s also helpful to look for logging history when they are saves in a file.
上面的示例显示我们可以将日志记录消息打印到文件而不是控制台。 如果有很多信息并且不方便在控制台中查看它们,这将非常有用。 更不用说在将日志保存到文件中时查找日志历史记录也很有帮助。
4. pdb (4. pdb)
The fourth way is to start the Python debugger pdb, let the program run in a single step mode, and you can check the running status at any time. The pdb is a Python’s build-in debugger tool. There are some other debugger tools such as web-pdb, pudb and so on. In most cases, the pdb is useful enough.
第四种方法是启动Python调试器pdb ,让程序以单步模式运行,您可以随时检查运行状态。 pdb是Python的内置调试器工具。 还有其他一些调试器工具,例如web-pdb , pudb等。 在大多数情况下, pdb足够有用。
一个基本的例子 (A Basic Example)
For example, we use pdb to run the following program step by step:
例如,我们使用pdb逐步运行以下程序:
s = '0'
n = int(s)
print(1000 / n)
Firstly, we start the pdb in terminal:
首先,我们在终端中启动pdb :
$ python -m pdb test.py
Now our program are running from the first line:
现在我们的程序从第一行开始运行:
> /home/yang/test.py(1)()
-> s = '0'
We can check the full code using command l
:
我们可以使用命令l
查看完整的代码:
(Pdb) l
1 -> s = '0'
2 n = int(s)
3 print(1000 / n)
Enter the command n
to run next line of our code:
输入命令n
以运行我们的代码的下一行:
(Pdb) n
> /home/yang/test.py(2)()
-> n = int(s)
(Pdb) n
> /home/yang/test.py(3)()
-> print(1000 / n)
(Pdb) n
ZeroDivisionError: division by zero
> /home/yang/test.py(3)()
-> print(1000 / n)
At any time, we can enter the command p
and a variable name to check this value is correct or not:
在任何时候,我们都可以输入命令p
和变量名来检查该值是否正确:
(Pdb) p s
'0'
(Pdb) p n
0
在代码中设置跟踪 (Set Trace in Code)
If there are lots of lines of our code, starting from the first line to use the pdb is very time consuming. We can use the function pdb.set_trace()
to set a breakpoint in our code. For example:
如果我们的代码有很多行,那么从第一行开始使用pdb非常耗时。 我们可以使用函数pdb.set_trace()
在代码中设置一个断点。 例如:
import pdb
s = '0'
n = int(s)
pdb.set_trace()
# The program will be paused and start pdb debugger
print(1000 / n)
If we run the above program, the result is:
如果我们运行上面的程序,结果是:
> /home/yang/test.py(7)()
-> print(1000 / n)
(Pdb)
Therefore, we can run the pdb from line the line of print(1000/n)
.
因此,我们可以从print(1000/n)
行开始运行pdb。
更方便的方式 (A More Convenient Way)
From Python 3.7, there is a build-in function breakpoint()
which can totally replace the pdb.set_trace()
.
从Python 3.7开始,有一个内置函数breakpoint()
可以完全替代pdb.set_trace()
。
s = '0'
n = int(s)
breakpoint()
print(1000 / n)
The result is identical with the result of using pdb.set_trace()
. Because breakpoint()
calls sys.breakpointhook()
function and this function calls pdb.set_trace()
by default.
结果与使用pdb.set_trace()
的结果相同。 因为breakpoint()
调用sys.breakpointhook()
函数,并且此函数默认情况下会调用pdb.set_trace()
。
There are some benefits of using breakpoint()
:
使用breakpoint()
有一些好处:
Obviously, using
breakpoint()
provides a little convenience because we don’t have to explicitly importpdb
module.显然,使用
breakpoint()
提供了一些便利,因为我们不必显式导入pdb
模块。More importantly, if we don’t like pdb and would like to use other debugger tools to replace it, there is no need to change our code.
更重要的是,如果我们不喜欢pdb并希望使用其他调试器工具来替换它, 则无需更改我们的代码。
For example, if we gonna use the web-pdb
(or other debugger tools) which may be better than the pdb
. The traditional method let us have to change every pdb.set_trace()
statement to web_pdb.set_trace()
(or other statement based on which tool are being used) in our code. Python should be elegant but this job is boring and not elegant at all.
例如,如果我们要使用可能比pdb
更好的web-pdb
(或其他调试器工具)。 传统方法使我们不得不在pdb.set_trace()
每个pdb.set_trace()
语句更改为web_pdb.set_trace()
(或其他基于使用哪个工具的语句)。 Python应该很优雅,但是这项工作很无聊,而且一点也不优雅。
Using breakpoint()
, no need to change code. We just need to change the environment variable PYTHONBREAKPOINT
at once.
使用breakpoint()
,无需更改代码。 我们只需要立即更改环境变量PYTHONBREAKPOINT
。
$ PYTHONBREAKPOINT = web_pdb.set_trace python3.7
We can also set this variable to zero, then all the breakpoints will be ignored and our program will run normally rather than start the debugger tool.
我们也可以将此变量设置为零,然后所有断点将被忽略,程序将正常运行,而不是启动调试器工具。
$ PYTHONBREAKPOINT = 0 python3.7
5.集成开发环境 (5. Integrated Development Environment)
If you want to set breakpoints and single-step execution more comfortably, you need an IDE (Integrated development environment) that supports debugging.
如果要更舒适地设置断点和单步执行,则需要支持调试的IDE(集成开发环境)。
The current good Python IDEs are:
当前好的Python IDE是:
Visual Studio Code: Python plug-in needs to be installed.
Visual Studio代码 :需要安装Python插件。
PyCharm: Great IDE designed for Python developers. By the way, this is my favourite Python IDE.
PyCharm :为Python开发人员设计的出色 IDE。 顺便说一句,这是我最喜欢的Python IDE。
Eclipse plus the “pydev” plug-in can also debug Python programs.
Eclipse加上“ pydev”插件也可以调试Python程序。
- … … ……
6.笔和纸 (6. Pen and Paper)
It sounds like a really traditional method but it can’t be ignored. Sometimes your mind is not very clear, writing it down with paper and pen is a good way to straighten out your thinking.
听起来像是一种非常传统的方法,但不能忽略。 有时您的想法不是很清楚,用纸和笔写下来是理清思路的好方法。
For example, I debugged a large project developed by others last year. There are lots of classes and complicated inheritance relationships between them. Unfortunately, there is no documents and even no code comments. In order to understand the relationships of classes, I wrote down the classes’ names and drew a draft diagram to help me sort their relationships out. After that, I found which one was wrong and caused the bug.
例如,我调试了其他人去年开发的一个大型项目。 它们之间有许多类和复杂的继承关系。 不幸的是,没有文档,甚至没有代码注释。 为了理解类的关系,我写下了类的名称并绘制了草稿图,以帮助我弄清它们之间的关系。 在那之后,我发现哪个是错误的并导致了该错误。
结论 (Conclusion)
Debugging is programmers everyday life. We can use all different debugging tricks to make our life easier.
调试是程序员的日常生活。 我们可以使用所有不同的调试技巧来使我们的生活更轻松。
Please leave your comments if you have some interesting debugging tricks.
如果您有一些有趣的调试技巧,请留下您的评论。
Thanks for reading. More Python related posts are here:
谢谢阅读。 更多与Python相关的文章在这里:
翻译自: https://medium.com/techtofreedom/six-debugging-techniques-for-python-programmers-cb25a4baaf4b
python程序调试