WEBVTT

00:00.240 --> 00:07.410
如果你想成为一个伟大的程序员, 让我们来谈谈一个非常重要的话题, 那就是调试｡ 

00:07.620 --> 00:11.000
没有人能写出完美的程序｡ 

00:11.010 --> 00:13.410
真的不可能｡ 

00:13.440 --> 00:17.430
我们总是会犯错误, 程序也在不断改进｡ 

00:17.640 --> 00:25.320
当我们发现越来越多的错误时, 我们不断地改进我们的代码, 因为程序在代码运行时充满了错误,

00:25.320 --> 00:29.730
或者我们称之为bug或异常｡

00:30.300 --> 00:38.790
你看, 从我们的代码中找到并删除这些bug或错误的行为被称为调试｡ 

00:39.000 --> 00:46.470
作为程序员, 我们大部分时间都在调试代码, 不管是我们自己的代码还是其他人的代码, 然后弄清楚, 嘿,

00:46.470 --> 00:49.560
为什么这不起作用？

00:50.010 --> 00:54.690
而且高级开发人员非常非常擅长调试｡ 

00:55.380 --> 01:02.370
在这段视频中, 我们来谈谈我对调试的一些建议, 以及一些好的做法｡

01:02.850 --> 01:07.380
现在, 请记住, 随着您编写代码的次数越来越多, 调试代码的能力也会越来越强｡ 

01:07.380 --> 01:12.150
所以你能做的最好的事情就是继续练习, 继续写Python代码｡ 

01:13.230 --> 01:14.940
我有什么建议？

01:14.970 --> 01:19.320
首先, 你肯定想用一些贷款｡ 

01:19.380 --> 01:21.250
什么是借贷？

01:21.270 --> 01:25.070
我们在设置开发人员环境时就已经讨论过了｡ 

01:25.080 --> 01:31.260
借出允许我们在编写代码时检测代码中的一些问题｡ 

01:31.290 --> 01:40.290
例如, 如果我在这里输入num加4, 我会得到一个红色下划线, 你会看到, 在我运行代码之前, Pi

01:40.290 --> 01:46.320
Flakes贷方就注意到了, 嘿, 有一个未定义的NUM｡

01:46.530 --> 01:51.510
因此, 借贷可以让我们在运行代码之前就发现这些错误｡ 

01:51.870 --> 01:59.550
我们看到我们可以使用像pi charm这样的ID, 它已经内置了借贷功能, 或者使用sublime text或Visual

01:59.550 --> 02:06.990
Studio代码, 并安装像PI lent这样的包和扩展, 以便在我们的代码中真正拥有借贷功能｡

02:07.020 --> 02:09.570
这是非常非常重要的工具｡ 

02:09.600 --> 02:15.480
接下来, 我建议始终使用某种ID或｡ 

02:16.380 --> 02:23.040
艾德, 因为这些编辑器和ID, 特别是那些特定于Python的, 比如Pi char,

02:23.070 --> 02:29.370
有所有这些内置的工具供我们使用, 比如基于Pep 8的自动格式化｡

02:29.370 --> 02:34.410
还记得Python社区的官方风格指南吗？

02:34.590 --> 02:42.600
它允许我们检测代码中的错误, 比如说, 突出显示和格式化代码｡ 

02:43.440 --> 02:47.670
因此, 在运行代码之前, 我们就可以很容易地检测到任何错误｡ 

02:48.240 --> 02:52.050
最后, 您希望能够学习阅读错误｡ 

02:52.350 --> 02:57.030
这是我试着和你们一起练习的东西, 正如我们所学到的, Python｡ 

02:57.330 --> 03:04.260
例如, 如果我做四加, 我们在这里说胡言乱语, 然后我单击“运行”｡ 

03:06.230 --> 03:06.950
马上就去

03:06.950 --> 03:07.410
我明白了｡ 

03:07.430 --> 03:10.080
嘿, 六号线｡ 

03:10.100 --> 03:13.370
我的主PI文件有错误｡ 

03:13.580 --> 03:19.310
有一个类型错误, 我在这里看到我试图添加int和一个字符串｡ 

03:19.950 --> 03:24.030
所以我们能够读取错误并理解它们的含义｡ 

03:25.380 --> 03:28.410
也许我会这样做｡ 

03:28.440 --> 03:29.790
如果我单击“运行”｡ 

03:30.490 --> 03:31.900
出现语法错误｡ 

03:33.110 --> 03:36.440
而我知道的一个语法错误意味着｡ 

03:36.440 --> 03:42.410
嘿, Python解释器试图读取我的代码, 但你刚才写的不是Python｡ 

03:42.410 --> 03:43.880
我不知道你在做什么｡ 

03:45.410 --> 03:45.890
给你

03:45.890 --> 03:49.180
在扫描字符串文字时, 我看到它已到达行尾｡ 

03:49.190 --> 03:55.670
所以我试着读这个字符串突然程序结束了就像你应该结束这个字符串一样, 记得吗？

03:56.770 --> 04:01.060
因此, 能够读取这些错误是非常非常重要的｡ 

04:01.450 --> 04:07.390
我们在这门课中讨论过其中的一些, 一些最常见的错误, 比如语法错误, 你写的东西,

04:07.390 --> 04:10.420
Python解释器无法理解｡

04:10.780 --> 04:13.210
我们有名字错误之类的东西, 对吧？

04:13.210 --> 04:16.720
我们使用了一个不存在的变量｡ 

04:17.710 --> 04:19.180
所以Python不理解｡ 

04:19.180 --> 04:20.970
嘿, 我不知道名字是什么｡ 

04:20.980 --> 04:22.810
名字有什么价值？

04:24.000 --> 04:25.650
我们有空气类型

04:25.680 --> 04:31.470
这就是我们不匹配数据类型的时候, 比如说一个字符串加四个｡ 

04:32.220 --> 04:34.740
我们有价值错误｡ 

04:35.470 --> 04:41.800
我们会遇到类似键错误的情况, 我们试图访问一个不存在的键, 或者属性错误,

04:41.800 --> 04:47.020
我们试图访问一个对象的方法, 但该方法不存在｡

04:47.710 --> 04:54.190
这些错误是我们在整个课程中经常看到的, 我们还会看到更多｡

04:54.580 --> 05:02.380
我想说的是, 大约有15到20个错误是真的, 真的很常见, 显示了90%的时间｡

05:03.230 --> 05:07.370
如果你记得的话, 你可以随时去Python文档中学习它们｡ 

05:07.370 --> 05:09.620
但这只是练习的结果｡ 

05:09.650 --> 05:16.260
如果您看到一个以前从未见过的错误, 我建议您在看到该错误后立即查看文档并阅读｡

05:16.280 --> 05:19.490
你通常会记得下一个问题｡ 

05:20.080 --> 05:23.920
但是让我向您展示我最喜欢的调试代码的方法｡ 

05:25.050 --> 05:30.570
它被称为PDB或Python调试器｡ 

05:31.080 --> 05:35.070
PDB是Python中的内置模块｡ 

05:36.270 --> 05:36.750
再来一次｡ 

05:36.750 --> 05:46.200
请记住, 我们的内置模块是Python自带的标准库的一部分, PDB是用于交互式解释器的Python调试器｡

05:47.400 --> 05:51.180
你可以在这里读到它, 但让我告诉你它是做什么的｡ 

05:52.460 --> 05:52.860
你看, 我是说...

05:52.880 --> 05:58.070
PDB非常有用, 因为它允许我们与代码进行交互｡ 

05:58.550 --> 06:08.210
所以之前我们有一个函数, 比如说我们有ADD函数, 我们有num1, num2,

06:08.630 --> 06:14.630
然后这个函数简单地返回num1加上num2｡

06:15.630 --> 06:24.930
在此之前, 如果我们想调试这段代码, 假设我们添加了四个, 再加上一些乱码, 它会给我们一个错误｡

06:26.760 --> 06:33.870
第一步, 我会采取的最有可能是添加一个打印在这里, 所以我可以说打印｡ 

06:33.870 --> 06:35.160
嘿, 这是怎么回事？

06:35.160 --> 06:35.610
让我看看, 我不知道

06:35.610 --> 06:38.130
一号和二号, 以及它给我的｡ 

06:38.970 --> 06:43.170
而打印是调试代码的一种非常非常快速和简单的方法｡ 

06:43.530 --> 06:48.480
我一直在用它, 但PDB给了我们一点额外的提升｡ 

06:49.780 --> 06:51.840
所以我们可以这样使用它｡ 

06:51.850 --> 07:01.540
我们只需导入PDB, 而不是使用类似print函数的东西, 我们可以简单地说, 让我在这里添加一个空格｡

07:01.540 --> 07:08.650
对于Python调试器, 我们可以简单地说PDB, 然后说set trace｡ 

07:09.310 --> 07:15.430
我认为set trace是导入的PDB对象上最有用的方法｡ 

07:16.520 --> 07:18.830
当我运行set方法时, 你会看到｡ 

07:22.300 --> 07:29.560
它现在给了我一个交互式的Python调试器, 我现在可以在这里输入命令, 并实际测试我的代码｡

07:30.290 --> 07:36.360
这是PDB中有趣的部分, 我就在第八行内｡ 

07:36.380 --> 07:41.630
因此, 我的代码试图运行, 但当它说PDB设置跟踪时, 它就暂停了｡ 

07:41.630 --> 07:48.170
现在我在这个世界上, 我可以测试出发生了什么, 这样我就可以说, 嘿, 第一个, 这是什么？

07:48.200 --> 07:49.400
嗯, 一号是四号｡ 

07:49.400 --> 07:50.420
二号怎么样？

07:50.750 --> 07:57.050
数字2是一个字符串, 我可以这样, 我试图把一个字符串和一个整型加起来, 这不起作用,

07:57.050 --> 08:00.050
所以我也可以用这种方法检测错误｡

08:00.680 --> 08:06.140
现在这个PDB互动实际上有很多有用的东西｡ 

08:06.140 --> 08:08.270
所以如果我在这里输入help｡ 

08:09.670 --> 08:10.300
你看到了吗？

08:10.300 --> 08:14.140
我有可以在PDB中使用的命令｡ 

08:14.260 --> 08:16.510
所以我这里有一吨｡ 

08:16.510 --> 08:21.510
我有exit, 我假设它会把我从这个PDB, Python调试器中退出｡ 

08:21.520 --> 08:23.020
但我也有｡ 

08:23.780 --> 08:24.710
事情就像｡ 

08:25.490 --> 08:26.570
比如说列表｡ 

08:26.570 --> 08:27.740
让我们看看list的作用｡ 

08:27.740 --> 08:31.970
所以当我在这里输入列表的时候, 现在这个网站真的是｡ 

08:32.820 --> 08:35.940
没有显示太多, 但希望您仍然可以看到列表｡ 

08:37.110 --> 08:38.940
我猜是某种输出｡ 

08:38.940 --> 08:46.410
我看到我得到了一个代码和OC的列表, 但是假设我不知道列表中什么做得好｡ 

08:47.280 --> 08:50.970
PDB允许我们键入, 帮助, 然后列出｡ 

08:51.670 --> 08:57.700
当我们这样做的时候, 它实际上给了我们文档, 就像我们这里一样｡ 

08:58.720 --> 09:00.820
如果我们去, 比方说, 列表｡ 

09:03.370 --> 09:03.910
让我想想｡ 

09:03.910 --> 09:05.470
列表, 列表, 列表, 列表

09:06.130 --> 09:06.880
就在这里｡ 

09:06.880 --> 09:09.520
它给我的文件就在这里｡ 

09:09.520 --> 09:12.160
所以它说列出当前文件的源代码｡ 

09:12.610 --> 09:12.880
好吧, 我会的

09:12.880 --> 09:15.940
所以它只列出了我们写的源代码｡ 

09:16.030 --> 09:17.080
好吧, 这很酷｡ 

09:17.080 --> 09:18.190
还有什么？

09:19.090 --> 09:25.330
嗯, 我们也有类似step或se的简称, step真的很酷｡ 

09:26.970 --> 09:29.910
让我们用clear把它放到顶部｡ 

09:29.910 --> 09:33.720
我将输入clear, 这样它将清除所有中断｡ 

09:35.480 --> 09:36.230
咱们干吧｡ 

09:37.400 --> 09:39.460
让我们把它放大一点, 这样你就能看到了｡ 

09:39.470 --> 09:39.970
你去那里｡ 

09:39.980 --> 09:40.580
这样好多了

09:40.610 --> 09:40.880
好吧, 我会的

09:40.880 --> 09:47.120
现在我可以执行类似step这样的操作, step将允许我们转到下一行｡ 

09:47.120 --> 09:49.850
所以, 如果我们再把它放大一点｡ 

09:50.860 --> 09:53.440
Step会说, 嘿, 去第九行｡ 

09:53.440 --> 09:54.370
让我们看看会发生什么｡ 

09:54.370 --> 09:55.660
我将按步骤键入｡ 

09:57.630 --> 09:57.840
哦, 我的天

09:57.840 --> 09:58.860
我还跳了两步｡ 

09:58.860 --> 09:59.910
那我们就向右走一步｡ 

10:01.730 --> 10:02.600
看看这个｡ 

10:02.720 --> 10:06.770
我转到代码中的下一行, 它就会找到我｡ 

10:06.800 --> 10:08.030
嘿, 你打错了吗？

10:08.030 --> 10:08.510
错误｡ 

10:08.540 --> 10:09.520
我们得到的错误｡ 

10:09.530 --> 10:11.250
我们在这里再加一行｡ 

10:11.270 --> 10:22.310
假设我们要把4加5或者4乘以5, 然后赋值给一个变量.

10:24.170 --> 10:26.450
如果我停下来再运行一次｡ 

10:28.570 --> 10:30.100
我现在在里面

10:30.130 --> 10:30.820
在这里｡ 

10:32.640 --> 10:35.310
如果我输入茶, 我会得到一个名字｡ 

10:35.310 --> 10:35.760
空气｡ 

10:35.880 --> 10:37.560
茶之所以没有定义, 是因为｡ 

10:37.560 --> 10:42.630
我在第八行的代码里, 但我们还没运行第九行｡ 

10:42.630 --> 10:44.220
那么我们来做一步｡ 

10:45.120 --> 10:46.800
现在我站在另一边｡ 

10:47.940 --> 10:52.950
所以如果我现在做pt, 我得到t等于20｡ 

10:53.190 --> 10:53.760
太棒了｡ 

10:53.760 --> 10:57.570
所以我可以逐步执行代码, 这非常非常有用｡ 

10:58.080 --> 11:03.720
我还有continue这样的功能, 它允许我继续执行代码, 直到返回一些东西, 然后继续并退出PDB,

11:03.720 --> 11:06.750
看看它｡

11:06.750 --> 11:07.620
我得到了错误｡ 

11:10.100 --> 11:11.570
我们再来一遍｡ 

11:11.600 --> 11:18.560
另一个有用的命令是a, a实际上给了我当前函数的所有参数.

11:18.560 --> 11:19.700
看看这个｡ 

11:19.700 --> 11:22.610
我得到了所有的论点, 这也是非常有用的｡ 

11:23.240 --> 11:25.190
还有命令w｡ 

11:25.860 --> 11:31.050
它向我显示了它正在执行的当前行的上下文｡ 

11:32.200 --> 11:35.710
所以你可以看到我们在哪里, 我们在广告中｡ 

11:36.240 --> 11:36.990
功能｡ 

11:38.130 --> 11:43.740
我们用这些参数调用了它, 现在我们要运行这一行｡ 

11:45.970 --> 11:48.040
最后, 当我们调试这个的时候｡ 

11:48.040 --> 11:51.460
好吧, 我想我终于看到我们有一个错误｡ 

11:51.460 --> 11:59.500
我们应该给它一个数字, 这样我就可以退出这里, 简单地把它固定为5｡ 

11:59.620 --> 12:02.950
所以现在我可以删除PDB和所有内容｡ 

12:02.950 --> 12:05.410
我的代码应该能正常工作｡ 

12:06.680 --> 12:07.280
太棒了｡ 

12:07.760 --> 12:12.710
因此, PTB是真棒, 通过您的代码和调试步骤, 并尝试不同的东西｡ 

12:12.710 --> 12:20.900
它确实需要一些练习, 但是在玩了一天PDB之后, 您将变得非常非常擅长调试｡

12:20.930 --> 12:28.730
看完这段视频后, 我建议你写PDB,

12:28.730 --> 12:37.010
希望你有一个足够大的Python文件, 你可以使用help和list来尝试不同的命令, 看看你有什么可用的｡

12:38.060 --> 12:39.710
实际上, 我想给你看最后一样东西｡ 

12:40.340 --> 12:44.210
假设我们返回到代码, 即PDB集合跟踪｡ 

12:44.780 --> 12:45.800
我单击“运行”｡ 

12:47.670 --> 12:53.430
我可以这样做吗, 我注意到我输入了A, 我有｡ 

12:53.430 --> 13:00.330
好的, 我的代码可以工作了, 但是我能把数字2改成等于一些乱码吗？

13:02.230 --> 13:04.320
好吧, 让我们看看我是否做下一个现在｡ 

13:06.100 --> 13:08.740
让我们接着运行最后一行｡ 

13:10.120 --> 13:11.140
我呼吸新鲜空气｡ 

13:11.200 --> 13:19.710
所以我也可以在这里修改变量, 写Python代码来测试我的函数｡ 

13:19.720 --> 13:21.190
这一点现在起作用了｡ 

13:21.190 --> 13:25.300
我可以测试一下, 如果我们把这个变量改成另一个值会发生什么？

13:26.220 --> 13:28.050
同样, 非常非常有用｡ 
