一 程序调试
在Python中,调试是指识别和修复程序中的错误和问题。 调试是程序开发过程中必不可少的一部分,合理利用调试工具和技术可以提高程序开发的效率和质量。Python提供了几种用于调试的工具和技术,帮助开发者找出程序中的bug并进行修复。以下是一些常用的Python程序调试技术:
1 使用print语句
简单粗暴地在代码中插入print语句,输出变量的值或程序执行的状态,以便跟踪程序的执行过程,查看程序执行过程中的变量状态。
def add_numbers(a, b):
print("a:", a)
print("b:", b)
result = a + b
print("result:", result)
return result
add_numbers(2, 3)
2 使用IDE的调试功能
许多集成开发环境(IDE)都提供了强大的调试功能,可以逐行执行代码,查看变量的值,检查栈跟踪等。常用的Python IDE,如PyCharm、Visual Studio Code、Spyder等都支持调试功能。
2.1 python自带的IDLE调试
(1)打开IDLE, 选择菜单栏的Debug—>Debugger,
(2)调出Debug Contorl 对话框,同时python shell窗口显示[DEBUG ON],表示已经处于调试状态
(3)然后再python shell 窗口中选择file,打开要调试的文件,如tickets.py
(4)在这个文件上添加需要的断点
设置断点后,程序执行到断点时会暂时终端执行,也可以随时操作继续。
添加断点的方法:在需要添加断点的所在行上,单击鼠标右键,在弹出的快捷菜单中选择SetBreakPoint,
设置断点后,所在行会变成黄色
(5) tickets.py 中点击Run,IDLE会输出交互,利用DebugControl 的Go 选项进行断点调试。
(6)DebugControl中的各项解释如下:
2.2 使用pycharm的调试功能
2.2.1 添加断点
鼠标选中需要设置断点的行,点击代码区左边竖栏,可以下断点,再次点击可以取消断点。如下图红色圆圈表示断点设置成功 。
2.2.2 运行调试模式
选择右上角的debug按钮或者alt+shift+F9,程序执行时会在下断点的位置停下来。
进入debug模式之后会出现如图下框。
上图红框的箭头的含义:
1.show execution point:显示当前所有断点。
2.step over:执行当前的函数或者语句,不会进入当前函数的具体方法,执行完当前的语句之后直接跳到下一句。(例:函数A内存在子函数a时,不会进入子函数a内执行单步调试,而是把子函数a当作一个整体,一步执行。)
3.step into:如果某行调用其他模块的函数,可以进入函数内部,会跳到调用函数的地方执行。(例:函数A内存在子函数a时,会进入子函数a内执行单步调试。)
4.step into my code:与step into是类似的,这个调试的话会进入调试的地方会更细有的时候会进入python本身的库函数执行的地方。
5.step out:返回到上一次的调试的位置。
6.run to cursor:直接跳到下一个断点(从现在的断点跳到打的下一个断点处)。
————————————————
原文链接:https://blog.csdn.net/cunrran/article/details/126975770
3 使用断点调试器pdb
Python提供了pdb模块,是Python调试器的标准库。可以通过在代码中插入import pdb; pdb.set_trace()
语句,在该位置设置一个断点,然后在运行程序时会暂停在断点处,允许你逐行查看代码并检查变量的值。 pdb模块,它是一个交互式调试器,可以在代码中插入调试器命令来检查程序状态。
import pdb
def divide_numbers(a, b):
pdb.set_trace() # 插入调试器命令
return a / b
result = divide_numbers(10, 0)
print("result:", result)
4 使用日志logging模块
通过在程序中添加日志记录,可以跟踪程序的执行过程并查看各个阶段的输出和变量值。logging模块是Python的内置模块,用于记录程序运行时的日志信息,可以帮助你更好地理解程序的执行流程。
import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
logging.debug("Debug message")
logging.info("Info message")
logging.warning("Warning message")
logging.error("Error message")
5 使用assert语句
assert语句用于检查代码中的条件是否满足,如果条件不满足,则抛出AssertionError异常。在程序中添加assert语句,可以在运行时检查程序的状态,如果断言失败,则会触发异常,帮助你快速发现问题所在。
def divide_numbers(a, b):
assert b != 0, "除数不能为0"
return a / b
result = divide_numbers(10, 0)
print("result:", result)
6 使用异常追踪
当程序出现异常时,Python会自动输出异常信息,包括异常类型、发生异常的位置和栈跟踪信息。通过查看异常信息,可以定位和修复错误。
要使用异常追踪进行调试,可以遵循以下步骤:
确定异常类型:当程序运行时发生异常,Python会告诉我们异常的类型,例如ZeroDivisionError、TypeError、ValueError等。首先要根据异常类型来定位问题的大致范围。
查看异常追踪信息:当异常发生时,Python会打印出异常追踪信息,其中包含了异常的类型、文件名、行号等信息。我们可以查看这些信息来了解异常发生的位置。
进行调试:根据异常追踪信息,我们可以找到导致异常的具体代码行。在该位置附近检查代码,查看变量的值,确保代码逻辑正确。可以使用print语句输出变量的值,或者使用Python的内置调试模块pdb进行交互式调试。
以下是一个示例,演示了使用异常追踪进行调试的过程:
def divide_numbers(a, b):
try:
result = a / b
return result
except ZeroDivisionError as e:
# 打印异常信息
print(f"Error: {e}")
# 打印异常追踪信息
import traceback
traceback.print_exc()
def main():
num1 = 10
num2 = 0
# 调用函数,可能会发生ZeroDivisionError异常
result = divide_numbers(num1, num2)
print(f"Result: {result}")
if __name__ == "__main__":
main()
在上面的示例中,函数
divide_numbers
用于计算两个数的商,当除数为0时会发生ZeroDivisionError异常。在main
函数中调用divide_numbers
函数,并捕获异常。如果异常发生,我们打印异常信息和异常追踪信息。通过观察异常追踪信息,我们可以知道异常发生的位置在
divide_numbers
函数的第三行,帮助我们快速定位问题所在。使用异常追踪进行调试可以帮助我们快速定位代码中的问题,并修复错误,提高代码的稳定性和可靠性。
7 使用代码分析工具
Python中有一些代码分析工具,如pylint
和pyflakes
,可以帮助你找出代码中的错误和潜在问题。
7.1 Pylint
Pylint是一个强大的静态代码分析工具,可以检查Python代码的语法错误、风格问题和潜在的bug。它会对代码进行严格检查,并生成详细的报告。
示例:在终端bash运行以下命令,对指定的Python文件进行静态代码分析。
pylint your_file.py
7.2 Pyflakes
Pyflakes是另一个轻量级的静态代码分析工具,用于查找Python代码中的错误和问题。它主要关注于语法错误和未使用的变量。
示例:在终端运行以下命令,对指定的Python文件进行代码检查。
pyflakes your_file.py
7.3 Flake8
Flake8是一个集成了Pylint、Pyflakes和PEP8检查的代码分析工具,它可以同时检查代码的语法、风格和错误。
示例:在终端运行以下命令,对指定的Python文件进行代码检查。
flake8 your_file.py
7.4 Bandit
Bandit是一个专门用于检查Python代码中安全问题的工具,它可以帮助你找出潜在的安全漏洞和风险。
示例:在终端运行以下命令,对指定的Python文件进行安全性分析
bandit your_file.py
使用这些代码分析工具,我们可以快速发现代码中的问题,并及时进行修复,从而提高代码的质量和可维护性。建议在开发过程中定期运行代码分析工具,以确保代码的健壮性和安全性。
二 如何将调试代码与正式代码分开
在编写正式代码时,通常应该避免在其中包含调试代码和调试语句,以确保代码的可读性和可维护性。调试代码和调试语句主要用于在开发阶段帮助我们调试程序,定位问题和查找错误。在正式代码中保留这些调试代码可能会影响代码的性能和稳定性,而且不利于代码的维护。
因此建议 在调试过程中,建议将调试代码和调试语句与正式代码分开,以避免在生产环境中产生不必要的输出或影响程序性能。调试完毕后,记得及时清理调试代码和语句。
为了将调试代码和调试语句与正式代码分开,可以考虑以下方法:
(1)使用条件判断
在编写调试代码时,使用条件判断语句来控制代码的执行。例如,可以使用if语句来判断是否处于调试模式,只有在调试模式下才执行调试代码。
DEBUG_MODE = True
if DEBUG_MODE:
# 调试代码
print("Debugging...")
# 正式代码
# ...
(2)使用日志记录
在调试代码中,可以使用日志记录来输出调试信息,而不是直接在控制台打印调试信息。这样可以方便地开启或关闭调试信息的输出。
import logging
logging.basicConfig(level=logging.DEBUG)
# 调试代码
logging.debug("Debugging...")
# 正式代码
# ...
(3)使用断言
在调试代码中,可以使用断言来进行条件检查,如果断言失败,则会抛出AssertionError异常。这可以帮助我们在调试时快速定位问题。
DEBUG_MODE = True
if DEBUG_MODE:
# 调试代码
assert some_condition, "Some condition failed."
# 正式代码
# ...
通过以上方法,我们可以有效地将调试代码和调试语句与正式代码分开,从而确保在正式环境中不会执行调试代码,提高代码的可靠性和性能。同时,在需要调试时,只需要简单地调整相关的调试标志或参数即可开启调试模式。