帮助你调试 Python 代码的5个技巧

引言

调试是程序员的一项基本技能,是一门手艺,我们需要不断练习才能做得更好。在这里,我总结了调试 Python 代码的有用技巧和工具。

1. 查看函数或对象的源代码

了解实现的细节对于调试至关重要。在调试 Python 代码时,你可能想知道模块、类、方法、函数、回溯、框架或代码对象的源代码。检查模块将帮助你:

import inspect
def add(x, y):
    return x + y
class Dog:
    kind = 'dog'         # class variable shared by all instances
    def __init__(self, name):
        self.name = name    # instance variable unique to each instance
    def eat(food):
        print("eating ..." + food)
print(inspect.getsource(add))    
print(inspect.getsource(Dog))
print(inspect.getsource(Dog.eat))

2. 把日志打印到文件中

日志是我们理解代码运行时最重要的线索。打印出日志是跟踪程序执行流程的有用方法。

但是,用 Python 打印只能输出到终端,对于复杂的故障排除,尤其是对于服务器端应用程序来说,这远远不是理想的方法。

Python 3中的 print 函数更加强大,因为它可以接受更多的参数,并且指定一些参数可以将 print 的内容输出到日志文件中。

with open('test.log', mode='w') as f:
    print('hello, python', file=f, flush=True)

另一个有用和灵活的模块是日志,我们可以设置输出文件名,日志格式等。

import logging
logging.basicConfig(filename='app.log', filemode='w', 
    format='%(name)s - %(levelname)s - %(message)s')
a = 5
b = 0
try:
  c = a / b
except Exception as e:
  logging.exception("Exception occurred")

3. 追踪执行时间

对于性能问题,我们需要计算一个函数的运行时间:

import time
start = time.time()
# run the function
end = time.time()
print(end-start)

有一个内置的模块叫做 timeit,我们可以使用它只用一行代码来跟踪时间:

import time
import timeit
def run_sleep(second):
    print(second)
    time.sleep(second)
print(timeit.timeit(lambda :run_sleep(2), number=1))

4. 交互式调试

REPL 支持增量交互式开发风格,交互式调试是一种更有效的方式。理想的工作流是重复的编辑运行过程。

要调用具有交互式会话的程序,我们需要添加-i 选项:

python -i demo.py

为了简化您的工作,importlib.reload (module)是避免重新启动交互式会话的合适方法。

让我们举个例子,假设我们运行了一个名为 demo 的函数,为了解决一个问题,我们需要对这个函数做一些修改,然后 reload (module)将加载修改后的 demo 版本,而不需要重新启动会话:

>>> from importlib import reload
>>> import demo from module
>>> demo()
"The result of demo..."
# Make some changes to "demo"
>>> demo()
"The result of demo..."  # The Outdated result
>>> reload(module)  # Reload "module" after changes made to "demo"
>>> demo()
"This will be the new result..."
>>> # repeat the circle of fix-and-retry

这将节省大量的调试时间。

5. 使用 pdb

Python 有一个名为 pdb 的模块来支持交互式源代码调试器。它支持在行级设置断点,即单步执行。此外,pdb 打印检查堆栈帧,变量值,检查源代码等。

要使用调试器启动程序,请添加-m pdb选项以调用脚本:

user@coderscat:~/snippets$ python3.7 -m pdb demo.py 
> /home/user/snippets/demo.py(1)<module>()
-> import inspect
(Pdb) l
  1  -> import inspect
  2  
  3     def gcd(a,b):
  4         if(b==0):
  5             return a
  6         else:
  7             return gcd(b,a%b)
  8  
  9  
 10     print(gcd(34, 34))
[EOF]
(Pdb) b demo.py:3
Breakpoint 1 at /home/user/snippets/demo.py:3
(Pdb) c
> /home/user/snippets/demo.py(3)<module>()
-> def gcd(a,b):
(Pdb) step
> /home/user/snippets/demo.py(10)<module>()
-> print(gcd(34, 34))
(Pdb)

从正在运行的程序中断调试器的另一个典型用法是插入:

import pdb; pdb.set_trace()

下面是一些有用的 pdb 命令

· list(l):显示 Python 解释器当前所在的代码行

· step(s):逐行继续执行,逐步执行函数

· next(n) : 继续下一行代码

· break(b) : 在当前行上设置新断点

· continue(c) : 继续执行,直到下一个断点

在大多数情况下,我们不需要执行所有步骤,pdb 是调试 Python 程序的终极工具。

总结

在调试 Python 代码时,可以尝试这些技巧和工具。为了提高你的调试技巧,熟能生巧!

·  END  ·


HAPPY LIFE


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值