专栏首页Opensource翻译专栏Python DeBug的7个步骤【Programming】

Python DeBug的7个步骤【Programming】

学习一些技巧,以最大程度地减少跟踪代码失败原因所花费的时间。

图片来源: Internet Archive Book Images. Modified by Opensource.com. CC BY-SA 4.0

现在是星期五下午三点。 为什么? 因为总是在星期五下午三点出事。 您会收到一个通知,说客户发现了您的软件中的一个 bug。 克服最初的疑虑后,您可以联系DevOps来了解应用日志的状况,因为您记得收到了有关它们已被移动的通知。

事实证明,它们是在你无法到达的地方,但它们正在被移动到 web 应用程序的过程中——所以你将拥有漂亮的应用程序来搜索和阅读它们,当然,它还没有完成。 可能过几天就好了。 我知道,这是完全不现实的情况,对吧? 不幸的是,日志或日志消息似乎经常在错误的时间出现。 在我们追踪这个 bug 之前,有一个公共服务公告:检查你的日志,确保它们在你认为它们在的地方,并定期记录你认为它们应该记录的内容。 当你不注意的时候,这些事情就会发生变化,真是令人惊讶。

好的,那么你找到了日志或者尝试响应,确实,客户发现了一个 bug。 也许你甚至认为你知道漏洞在哪里。

你立即打开你认为可能是问题的文件,并开始四处查看。

1. 先别动你的代码

继续研究它,甚至可能提出一个假设。 但是,在开始编写代码之前,请接受那个创建 bug 的调用,并将其转换为测试。 这将是一个集成测试,因为尽管您可能有怀疑,但是您还不知道问题的确切位置。

确保这个测试失败。 这一点很重要,因为有时候你所做的测试并没有模仿失败的调用; 如果你正在使用一个网络或其他框架来模糊测试,这一点尤其重要。 许多东西可能存储在变量中,但不幸的是,仅仅通过查看测试,就不能总是很明显地看到您在测试中所做的调用。 我不会说我创建了一个测试,当我试图模仿一个错误调用时,它通过了测试,但是,嗯,我做到了,我不认为这是特别不寻常的。 从我的错误中吸取教训。

2. 写一个失败的测试

现在已经有了一个失败测试,或者可能是一个带有错误的测试,是时候进行故障排除了。但是在这样做之前,让我们先回顾一下堆栈,因为这使故障排除更加容易。

堆栈由所有已经开始但尚未完成的任务组成。所以,如果你烤了一个蛋糕,然后把面粉加入面糊中,那么你的面糊堆是:

  • 做蛋糕
  • 做面糊
  • 加面粉

你已经开始做你的蛋糕,你已经开始做面糊,正在加入面粉。往锅里加油不在清单上,因为你已经完成了,制作糖霜也不在清单上,因为你还没开始做。

如果你在堆栈上是模糊的,我强烈建议使用 Python Tutor,在那里你可以观察堆栈当你执行代码行。

现在,如果您的Python程序出了问题,解释器会帮助您打印出堆栈。这意味着,不管这个程序当时在做什么,很明显,有些地方出了问题,这些问题都在底部。

3.总是先检查堆栈的底部

您不仅可以在堆栈的底部看到发生了哪个错误,而且通常堆栈的最后一行也是您可以找到问题的地方。如果底部没有帮助,并且你的代码已经有一段时间没有被连接了,那么运行它将是非常有帮助的。我推荐pylint或者flake8。通常情况下,它指向了我一直忽略的错误。

如果这个错误看起来晦涩难懂,你的下一步可能就是谷歌一下。如果不包含仅与代码相关的信息,比如变量名、文件名等,那么运气会更好。如果您使用的是python3(您应该使用python3),那么在搜索中包含3会很有帮助;否则,python2解决方案往往会占据搜索结果的顶部。

曾几何时,开发人员不得不在没有搜索引擎帮助的情况下进行故障排除。这是一个黑暗的时代。所以请充分利用所有可用的工具。

不幸的是,有时问题发生得更早,只有在堆栈底部执行的行中才会显现出来。想想看,当蛋糕没有起酥的时候,忘记加发酵粉是多么的明显。

是时候查看一下堆了。很有可能问题出在代码中,而不是Python核心,甚至不是第三方软件包,所以先扫描堆栈,在代码中寻找代码行。另外,在自己的代码中设置断点通常要容易得多。将断点粘贴在代码堆栈的上面一点,然后环顾四周,看看事情是否看起来像它们应该的那样。

“但是Maria,”我听到你说,“如果我有一个堆栈跟踪,这些都是有帮助的,但是我只有一个失败的测试。我该从哪里开始呢?”

Pdb,Python调试器。

在您的代码中找到一个您知道此调用应该命中的位置。你至少应该能找到一个地方。在这里插入一个pdb断点。

题外话

为什么不是一个打印声明?我过去常常依赖于打印语句。它们有时仍然派得上用场。但是一旦我开始处理复杂的代码库,尤其是那些打网络电话的代码库,打印就变得太慢了。最后我发现到处都是印刷的声明,我不知道它们在哪里,为什么,事情变得复杂起来。但主要使用pdb还有一个更重要的原因。比方说,你放入一个print语句,然后发现有些地方出错了——而且一定是早些时候出错了。但是看看你把print语句放在哪里的函数,你不知道你是怎么到那里的。查看代码是一个很好的方式来了解你将要去的地方,但是对于了解你去过的地方来说是很糟糕的。是的,我已经在我的代码库中查找了一个函数调用的位置,但是这可能会变得很乏味,并且对于一个流行的函数来说并不能缩小范围。Pdb非常有用。

您按照我的建议,插入pdb断点并运行测试。然后它嗖的一声就过去了,又失败了,没有休息。保留断点,然后在测试套件中运行一个测试,该测试执行与故障测试非常相似的操作。如果您有一个不错的测试套件,那么您应该能够找到一个测试,它所碰到的代码与您认为失败的测试所碰到的代码相同。运行该测试,当它到达断点时,按下w并查看堆栈。如果通过查看堆栈,您不知道另一个调用是如何或者在哪里出错的,那么在堆栈中找到属于您的一些代码,并在该文件中放置一个断点,在堆栈跟踪中的断点之上放置一行。再试一次新的测试。继续前后移动,顺着堆栈向上移动,找出您的调用偏离轨道的地方。如果您一直到达跟踪的顶部而没有遇到断点,那么恭喜您,您已经发现了问题:您的应用程序拼写错误。这里没有经验,没有,一点也没有。

4. 改变事物

如果你仍然感到迷茫,试着做一个新的测试,稍微改变一下。 你能让新的测试起作用吗? 有什么不同? 什么是一样的? 试着改变一些其他的东西。 一旦您完成了测试,也许还有其他测试,就可以开始修改代码中的内容,看看是否可以缩小问题的范围。 记住,以全新的提交来开始故障排除,这样您就可以轻松地退出不起作用的更改。 (这是对版本控制的引用,如果您不使用版本控制,它将改变您的生活。嗯,也许它会使编码变得更容易。有关详细介绍,请参考“ 版本控制的可视指南 ”)

5. 休息一下

严肃地说,当它不再像一个有趣的挑战或游戏,开始变得真正令人沮丧时,你最好的行动就是离开问题。休息一下。我强烈建议去散散步,试着想想别的事情。

6.把所有事情都写下来

当你回来的时候,如果你没有突然受到启发去尝试一些事情,写下你所知道的关于这个问题的任何信息。这应包括:

  • 是什么引起了问题
  • 到底发生了什么,包括任何错误消息或相关的日志消息
  • 您所期望的结果
  • 到目前为止,您已经完成了哪些工作来查找问题和在故障排除过程中发现的任何线索

有时候这些信息太多了,但是相信我,试图从一个人那里获取零碎的信息真的很烦人。尽量简洁,但要完整。

7.寻求帮助

我经常发现,仅仅写下所有的信息就会触发我对一些我还没有尝试过的事情的想法。当然,有时候在点击提交按钮后,我会立即意识到问题所在。无论如何,如果你在把所有事情都写下来之后仍然没有想到任何事情,试着给某人发一封邮件。首先,尝试与你的项目有关的同事或其他人,然后再进行项目电子邮件列表。不要害怕寻求帮助。大多数人都很友好,乐于助人,我发现在Python社区中这一点尤其明显。

玛丽亚·麦金莱(Maria McKinley)将于2月23日至24日在西雅图举行的PyCascades 2019上展示《Hunting the Bugs》 。

原文链接:https://opensource.com/article/19/2/steps-hunting-code-python-bugs

原文作者:Maria Mckinley

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 强大的文本分析工具,awk入门【Programming】

    Awk是Unix和类似Unix系统下功能强大的文本分析工具,但是因为它具有可用于执行常见解析任务的编程函数,因此也被视为一种编程语言。 您可能不会使用awk开发...

    Potato
  • 为什么要使用 GraphQL?【Programming】

    正如我之前所写, GraphQL是下一代API技术,它正在改变客户端应用程序与后端系统的通信方式以及后端系统的设计方式。

    Potato
  • 如何使用Sphinx记录Python代码【Programming(Python)】

    文档是开发过程的最佳组成部分。 Sphinx与Tox一起,使得它易于编写,易于欣赏。

    Potato
  • 美团外卖订单中心的演进 转

    美团外卖从2013年9月成交第一单以来,已走过了三个年头。期间,业务飞速发展,美团外卖由日均几单发展为日均500万单(9月11日已突破600万)的大型O2O互联...

    chinotan
  • C++STL模板库适配器之queue队列

    队列是先进先出的数据结构. 在STL中使用 queue表示. 底层使用的是序列容器deque,或者list 不能使用vector因为vector可以说底层是数...

    IBinary
  • 深度学习算法优化系列二 | 基于Pytorch的模型剪枝代码实战

    昨天讲了一篇ICLR 2017《Pruning Filters for Efficient ConvNets》 ,相信大家对模型剪枝有一定的了解了。今天我就剪一...

    BBuf
  • 深入理解Python异步编程(上)

    彻底理解异步编程是什么、为什么、怎么样。深入学习asyncio的基本原理和原型,了解生成器、协程在Python异步编程中是如何发展的。

    SeanCheney
  • SAP CRM里note界面默认语言的决定逻辑

    我们在note assignment block里点了new之后的creation页面里的Language default value = log on lan...

    Jerry Wang
  • Scala教程之:Future和Promise

    在scala中可以方便的实现异步操作,这里是通过Future来实现的,和java中的Future很相似,但是功能更加强大。

    程序那些事
  • 编写难于测试的代码的5种方式

    有一次,我在一个讲座上听到主持人问听众如何故意编写难于测试的代码。在场的小伙伴都惊呆了,因为没有任何人会故意写这种糟糕的代码。我记得他们甚至给不出一个好的答案。

    哲洛不闹

扫码关注云+社区

领取腾讯云代金券