如何使用交互式控制台调试Python

来自菜鸟教程
跳转至:导航、​搜索

介绍

调试 是软件开发过程的一部分,程序员在此寻找并解决阻止软件正常运行的问题。

一个有用且快速的调试工具是 Python 代码模块 ,因为它可以用来模拟交互式解释器。 该模块还为您提供了试验用 Python 编写的代码的机会。

先决条件

您应该在您的计算机或服务器上安装 Python 3 并设置编程环境。 如果您没有设置编程环境,您可以参考本地编程环境或服务器上的编程环境适合您的操作的安装和设置指南系统(Ubuntu、CentOS、Debian 等)

了解 code 模块

您可以 将代码模块 添加到您的 Python 程序中,以指示程序停止执行并进入交互模式,以检查您的代码是如何工作的,而不是使用调试器单步执行代码。 code 模块是 Python 标准库的一部分。

这很有用,因为您可以在不牺牲编程文件可以提供的复杂性和持久性的情况下利用解释器。 通过使用 code 模块,您可以避免在整个代码中使用 print() 语句作为调试的一种形式,随着时间的推移会变得笨拙。

要将模块用作调试方法,您可以使用模块的 interact() 函数,它会在程序被调用时停止执行,并为您提供一个交互式控制台,以便您可以检查程序的当前状态。

Info: 要跟随本教程中的示例代码,请通过运行 python3 命令在本地系统上打开 Python 交互式 shell。 然后,您可以通过在 >>> 提示符后添加示例来复制、粘贴或编辑示例。


该函数及其可能的参数如下:

code.interact(banner=None, readfunc=None, local=None, exitmsg=None)

这个函数运行一个 read-eval-print 循环,并创建一个 InteractiveConsole 类 的对象实例,它模拟交互式 Python 解释器的行为。

可选参数如下:

  • banner 可以设置为 string,以便您可以标记解释器的启动位置
  • readfunc 可以用作 InteractiveConsole.raw_input() 方法
  • local 将为解释器循环设置默认命名空间
  • exitmsg 可以设置为一个字符串来说明解释器在哪里结束

使用 local 参数,您可以使用,例如:

  • local=locals() 用于本地命名空间
  • local=globals() 用于全局命名空间
  • local=dict(globals(), **locals()) 同时使用全局命名空间和当前本地命名空间

请注意,exitmsg 参数是 Python 3.6 的新参数,因此如果您使用的是旧版本的 Python,请更新它或不使用 exitmsg 参数。

您可以将 interact() 函数放置在程序中的任何位置,以在代码中启动交互式解释器。

使用 code 模块

让我们在一个名为 balances.py 的银行账户余额程序的上下文中来看看这个。 我们将 local 参数设置为 locals() 以将命名空间设置为本地。

余额.py

# Import code module
import code

bal_a = 2324
bal_b = 0
bal_c = 409
bal_d = -2

account_balances = [bal_a, bal_b, bal_c, bal_d]


def display_bal():
    for balance in account_balances:
        if balance < 0:
            print("Account balance of {} is below 0; add funds now."
                  .format(balance))

        elif balance == 0:
            print("Account balance of {} is equal to 0; add funds soon."
                  .format(balance))

        else:
            print("Account balance of {} is above 0.".format(balance))

# Use interact() function to start the interpreter with local namespace
code.interact(local=locals())

display_bal()

我们使用带有 local=locals() 参数的函数 code.interact() 来使用本地命名空间作为解释器循环中的默认值。

让我们运行上面的程序,如果我们不在虚拟环境中使用 python3 命令,或者如果我们在虚拟环境中使用 python 命令:

python balances.py

运行程序后,我们最初将收到以下输出:

Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 

您的光标将放置在 >>> 行的末尾,就像在 Python 交互式 shell 中一样。

从这里,您可以发出对打印变量、函数等的调用:

>>> print(bal_c)
409
>>> print(account_balances)
[2324, 0, 409, -2]
>>> print(display_bal())
Account balance of 2324 is 0 or above.
Account balance of 0 is equal to 0, add funds soon.
Account balance of 409 is 0 or above.
Account balance of -2 is below 0, add funds now.
None
>>> print(display_bal)
<function display_bal at 0x104b80f28>
>>> 

我们看到,通过使用本地命名空间,我们能够打印变量并调用函数。 最后的 print() 调用显示了函数 display_bal 在计算机内存中的位置。

一旦您对使用解释器能够检查的内容感到满意,您可以按 CTRL + D(对于基于 *nix 的系统)或 CTRL + Z(对于基于 Windows 的系统)离开控制台并继续执行程序。

如果您想离开控制台而不运行程序的其余部分,您可以通过键入 quit() 来完成,程序将被中止。

要利用 bannerexitmsg 参数,我们可以这样做:

余额.py

...
# Use interact() function to start the interpreter
code.interact(banner="Start", local=locals(), exitmsg="End")

display_bal()

当我们运行程序时,我们会在运行程序时收到以下输出:

Start
>>> 

使用 banner 参数可以让您在代码中设置多个点并让您能够识别它们。 例如,您可以使用打印 "In [for-loop](how-to-construct-for-loops-in-python-3)"banner 和打印 "Out of for-loop"exitmsg,这样您就可以准确地知道您在代码中的位置。

从这里,我们可以像往常一样使用解释器。 一旦我们输入 CTRL + D 退出解释器,我们将收到退出消息并且函数将运行:

End
Account balance of 2324 is 0 or above.
Account balance of 0 is equal to 0, add funds soon.
Account balance of 409 is 0 or above.
Account balance of -2 is below 0, add funds now.

该程序现在已在交互式会话之后完全运行。

使用 code 模块调试代码完成后,您应该删除 code 函数和 import 语句,以便您的程序照常运行。 code 模块提供了一个实用程序,所以一旦你完成后自己清理是很重要的。

结论

使用 code 模块启动交互式控制台可以让您在粒度级别查看代码正在执行的操作,以了解其行为并根据需要进行更改。 想了解更多,可以阅读代码模块官方文档。

要了解有关可用于调试 Python 代码的其他方法的更多信息,请阅读我们关于 如何使用 Python 调试器 pdb 的教程,以及我们关于 如何使用日志记录 的教程。