【问题标题】:Why does error traceback show edited script instead of what actually ran?为什么错误回溯显示编辑的脚本而不是实际运行的脚本?
【发布时间】:2019-08-24 19:19:33
【问题描述】:

背景

考虑以下最小示例:

当我保存以下脚本并从终端运行时,

import time

time.sleep(5)
raise Exception

代码会在休眠 5 秒后报错,留下以下回溯。

回溯(最近一次通话最后一次):

中的文件“test/minimal_error.py”,第 4 行 引发异常
例外

现在,比如说,我运行脚本,在 5 秒睡眠期间,我在中间添加了一行。

import time

time.sleep(5)
a = 1
raise Exception

python解释器从睡眠中醒来并到达下一行raise Exception后,会引发错误,但会留下以下回溯。

回溯(最近一次通话最后一次):

中的文件“test/minimal_error.py”,第 4 行 a = 1
例外

所以明显的问题是它不打印导致错误的实际代码。虽然它给出了正确的行号(正确地反映了正在运行的脚本的版本,虽然可以理解无用)和正确的错误消息,但我真的不知道是哪段代码实际导致了错误。

在实际实践中,我实现了程序的一个部分,运行它以查看该部分是否运行良好,当它仍在运行时,我继续执行下一个我必须实现的事情。当脚本抛出错误时,我必须找到导致错误的实际代码行。我通常只是阅读错误消息并尝试推断导致它的原始代码。有时不容易猜到,所以我将脚本复制到剪贴板并通过在运行脚本后撤消我编写的内容来回滚代码,检查导致错误的行,然后从剪贴板粘贴回来。

问题

解释器显示a = 1,这是代码的“当前”版本的第4行,而不是raise Exception,这是代码的“运行”版本的第4行,有什么可以理解的原因吗?如果解释器知道“第 4 行”导致了错误并且错误消息是“异常”,为什么不能说命令raise Exception 引发了它?

我不太确定这个问题在这里是否是主题,但我认为我不能从help center 所说的内容中得出结论。它是关于“程序员常用的[a]软件[工具]”(Python解释器),并且是“软件开发独有的实用、可回答的问题”,我认为。我不认为这是基于意见的,因为选择这种实施方式应该是有原因的。

(在 Python 2.7.16、3.6.8、3.7.2 和 3.7.3 中观察到相同,所以它似乎不是特定于版本的,而是在 Python 中发生的事情。)

【问题讨论】:

  • CristiFati,感谢您的链接!它所说的正是我所期望的,当我运行它时脚本被加载到内存中,这样对脚本文件的进一步编辑就不会影响 任何 行为。不幸的是,错误回溯并非如此,正如链接中的答案也指出(没有解释任何理由)。

标签: python interpreter


【解决方案1】:

直接原因是 Python 重新打开文件并再次读取指定的行以将其打印在错误消息中。那么,当它一开始就已经读取了文件时,为什么还需要这样做呢?因为它不会将源代码保存在内存中,只保存生成的字节码。

事实上,Python 永远不会一次将源文件的全部内容保存在内存中。相反,词法分析器将从文件中读取并一次生成一个标记,然后解析器将其解析并转换为字节码。一旦解析器处理完一个令牌,它就消失了。

所以回到原始源代码的唯一方法是再次打开源文件。

【讨论】:

  • 谢谢!我对这种行为不满意,但至少我能明白为什么它会这样......
【解决方案2】:

我认为这是here描述的经典问题。

Sleep 使用 os 系统调用来暂停该线程的执行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-29
    相关资源
    最近更新 更多