测试基础 测试基础-Python 篇 PyCharm 调试步骤及 Python 运行时常见错误

耿晓 · 2023年02月24日 · 最后由 叫我大哥9527 回复于 2023年02月27日 · 5885 次阅读

在编码过程中,调试代码占据了大部分时间,今天梳理下在 PyCharm 下调试代码的几个按钮的作用,以及常见的 Python 运行时错误。

Part One:PyCharm 调试步骤


图 1
我们在 PyCharm 运行代码时,可以通过上图中红色方框中的运行按钮。当然,如果代码中存在 “if name == 'main':” 语句,我们也可以点击其左边的运行按钮运行代码。需要注意的是,使用截图右上角红框中的运行按钮时,需要注意选择的是不是当前脚本,避免出现运行文件错误的情况。我在编码过程中,最常使用的是快捷键:"Ctrl+Shift+F10"

如果我们想要调试我们的代码,首先需要设置断点(在目标代码行左侧鼠标左击,会出现一个红色的点),然后点击调试按钮,调试按钮对应上图中的黄色方框,我们举例说明。

l = [1, 3, 2, 5, 0]

def bubble(l: list[int]) -> list[int]:
    n = len(l)
    for i in range(n):
        for j in range(n - i - 1):
            if l[j] > l[j + 1]:
                l[j], l[j + 1] = l[j + 1], l[j]
    return l

print(bubble(l))

如果我们想调试这个冒泡排序函数,那我们的断点可以打在函数的调用行,也就是"print(bubble(l))"所在行。我们也可以把断点打在函数内部,比如"n = len(l)"所在行。但是我们不能把断点打在函数定义行,也就是不能打在"def bubble(l: list[int]) -> list[int]:"行,因为如果在函数定义行打点,当调试器运行到函数定义处时,它将停在该处而不是在函数调用处停止,达不到预期效果。打完断点后,我们点击调试按钮即可。

在调试过程中,我们会使用到如下按钮,我们从左到右依次讲解:

图 2

  • Step Over:左边第一个,单步执行,快捷键:F8,用于单步执行当前行,并停留在下一行。具体表现为:如果我们在"print(bubble(l))"所在行打点,那么程序会直接运行完毕;如果我们在"n = len(l)"所在行打点,那么我们可以逐步看到函数内部的执行过程。

为了方便演示,我们修改一下上面的代码。

import requests

l = [1, 3, 2, 5, 0]

def len_v2(l: list) -> int:
    return len(l)

def bubble(l: list[int]) -> list[int]:
    n = len_v2(l)
    n2 = len([1, 2, 3])
    n3 = requests.Session()
    for i in range(n):
        for j in range(n - i - 1):
            if l[j] > l[j + 1]:
                l[j], l[j + 1] = l[j + 1], l[j]
    return l

print(bubble(l))
  • Step Into:左边第二个,单步跳入,快捷键:F7,用于单步执行当前行,调试器将进入当前代码行中调用的任何函数或方法,无论它们是来自您的代码还是来自第三方库。 具体表现为:我们将断点打在"print(bubble(l))"所在行。然后第一次点击"Step Into",调试器阴影会定位到 n = len_v2(l),如图 3。


图 3
因为"len_v2"是我自定义的方法,所以第二次点击"Step Into"后,调试器阴影会定位到"len_v2"方法内的"return len(l)"所在行,如图 4。

图 4
第三次点击"Step Into"后,调试器阴影又回到"n = len_v2(l)"所在行。

第四次点击"Step Into"后,调试器阴影来到"n2 = len([1, 2, 3])"所在行。

第五次点击"Step Into"后,调试器阴影来到"n3 = requests.Session()"所在行,这时有小伙伴可以疑惑,为什么没有进入到"len()"函数内部呢?是因为"Step Into"按钮本应该进入 len 模块的代码并执行该函数。但是,PyCharm 默认设置了 “不进入 Python 库源代码” 的选项,所以调试器将跳过 len 模块的源代码并继续执行下一行代码。有伙伴可能会再次提问:Python 标准库都有哪些模块呢?我也为大家找到了查看 Python 标准库的方法,放在了文章末尾,有兴趣的小伙伴可以查阅。

第六次点击"Step Into"后,调试器会进入到"requests.Session()"内部,如图 5。这次为什么又进来了呢?因为 requests 是第三方模块,也是就需要我们"pip install"安装的模块。

图 5

我们一般不需要调试第三方库的代码,所以我们点击"Step Out"按钮,调试器阴影就会有回到"bubble()"函数的"n3 = requests.Session()"行。
后续再点击"Step Into",效果就和点击"Step Over"效果一样了。

  • Step Into My Code:左边第三个,单步跳入,快捷键:Alt+Shift+F7,和按钮"Step Into"唯一的区别是单击"Step Into"按钮时,调试器将进入当前代码行中调用的任何函数或方法,无论它们是来自您的代码还是来自第三方库,但是当单击"Step Into My Code"按钮时,调试器将仅进入当前代码行中调用的您自己编写的函数或方法,如果当前行中的调用来自第三方库,则调试器将跳过该调用并直接停在下一行。
    具体表现为:相比上面"Step Into"的演示过程,这次只会进入我自定义的"len_v2()"函数内部,不会进入第三方模块"requests"内部。

  • Force Step Into:左边第四个,强制步入,快捷键:Alt+Shift+F7,用处不多,我几乎不用,所以不做过多介绍;

  • Step Out:左边第五个,跳过按钮,快捷键:Shift+F8,如果当前行位于函数内部,执行函数并跳过所有代码,直到该函数返回。这个很好理解,并且我们在演示"Step Into"按钮时就用到过,从"requests.Session()"内部跳回到"bubble()"函数。

  • Run To Curse:定位到游标处,快捷键:Alt+F9,调试器阴影直接切换到鼠标指定的地方。比如我们在调试"bubble()"时,虽然我们把断点打在了"print(bubble(l))"所在行,但如果我们将鼠标指针定位到"for i in range(n):"行后,点击"Run To Curse"按钮,那么调试器阴影直接切换到"for i in range(n):"行,跳过前面的步骤。

Part Two:Python 运行时常见错误

开门见山!

  • SyntaxError :invalid syntax

语法错误:无效语法

a === 1
print(a)
---------
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 4
    a === 1
        ^
SyntaxError: invalid syntax
  • IndentationError:unexpected indent

缩进错误:意料之外的缩进

 print(1)
--------
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 4
    print(1)
IndentationError: unexpected indent
  • IndentationError:unindent does not match any outer indetation level

缩进错误:缩进不匹配任何外部缩进级别

for i in range(5):
    print(i)
  print(i+1)
-----------------
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 6
    print(i+1)
              ^
IndentationError: unindent does not match any outer indentation level
  • IndentationError:expected an indented block

缩进错误:期望一个缩进块

for i in range(5):
print(i)
-----------------
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 5
    print(i)
    ^
IndentationError: expected an indented block
  • TypeError: 'list' object cannot be interpreted as an integer

类型错误:'list'对象不能被解释为整数

num=[1,2,3]
for i in range (num):
    print(num[i])
----------------------
Traceback (most recent call last):
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 6, in <module>
    for i in range (num):
TypeError: 'list' object cannot be interpreted as an integer
  • TypeError: 'str' object does not support item assignment

类型错误:“str” 对象不支持项赋值

s = 'hello'
s[0] = 'H'
print(s)
---------
Traceback (most recent call last):
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 5, in <module>
    s[0] = 'H'
TypeError: 'str' object does not support item assignment
  • TypeError: Can't convert 'int' object to str implicitly

类型错误:不能将 “int” 对象隐式转换为 str

variable = '2'
variable += 1
--------------
Traceback (most recent call last):
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 5, in <module>
    variable += 1
TypeError: Can't convert 'int' object to str implicitly
  • SyntaxError: EOL while scanning string literal

语法错误:扫描字符串文字时出现 EOL

file_path = 'd:\'
-----------------
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 4
    file_path = 'd:\'
                     ^
SyntaxError: EOL while scanning string literal
  • NameError: name 'fooba' is not defined

名称错误:名称 “fooba” 未定义

fooba()
--------
Traceback (most recent call last):
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 4, in <module>
    fooba()
NameError: name 'fooba' is not defined
  • AttributeError: 'str' object has no attribute 'lowerr'

属性错误:字符类型没有'lowerr'属性

s = 'hello'
s.lowerr()
----------
Traceback (most recent call last):
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 5, in <module>
    s.lowerr()
AttributeError: 'str' object has no attribute 'lowerr'
  • IndexError: list index out of range

索引错误:索引越界

l = [1,2,3]
print(l[4])
----------
Traceback (most recent call last):
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 5, in <module>
    print(l[4])
IndexError: list index out of range
  • KeyError: 'zebra'

键错误:'zebra'

d = {'name':'Tom'}
print(d['zebra'])
--------------------
Traceback (most recent call last):
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 5, in <module>
    print(d['zebra'])
KeyError: 'zebra'
  • UnboundLocalError: local variable 'x' referenced before assignment

未绑定局部变量错误:局部变量'x'在赋值前被引用

x = 10

def my_func():
    print(x)
    x = 20

my_func()
--------------
Traceback (most recent call last):
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 10, in <module>
    my_func()
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 7, in my_func
    print(x)
UnboundLocalError: local variable 'x' referenced before assignment
  • TypeError: 'range' object does not support item assignment

类型错误:'range'对象不支持元素赋值

my_range = range(5)
my_range[0] = 1
-----------------------
Traceback (most recent call last):
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 5, in <module>
    my_range[0] = 1
TypeError: 'range' object does not support item assignment
  • TypeError: myMethod() takes 1 positional argument but 2 were given

类型错误:myMethod() 函数接受 1 个位置参数,但是给了 2 个

def myMethod(a):
    return a

myMethod(1,2)
-------------------
Traceback (most recent call last):
  File "G:\gxyPocket\PycharmProjects\TanAutoTools\debug_practice\practice.py", line 7, in <module>
    myMethod(1,2)
TypeError: myMethod() takes 1 positional argument but 2 were given

Python 运行时常见错误差不多就这些,平时多和 Error 见见面,等调试的时候就不那么发憷了🤗

查看 Python 标准库的方法

  1. 打开 Python 官方文档网站 https://docs.python.org/3/library/ ,这是 Python 3 版本的标准库文档。如果您使用的是其他版本的 Python,请在网站的右上角选择相应的版本。

  2. 在页面左侧,您将看到一个包含所有标准库模块名称的列表。您可以单击列表中的任何模块名称,以查看有关该模块的详细文档。

  3. 如果您不知道要查找的模块的名称,可以使用文档中的搜索框。在搜索框中键入您要查找的模块名称或关键字,然后单击搜索按钮。文档将显示包含您的搜索关键字的所有模块的列表。单击列表中的任何模块名称,以查看有关该模块的详细文档。

共收到 1 条回复 时间 点赞
耿晓 测试基础-Python 篇 琐碎但十分实用的知识点 中提及了此贴 02月24日 17:14

平时多和 Error 见见面,等调试的时候就不那么发憷了~

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册