为什么错误回溯显示已编辑的脚本而不是实际运行的脚本?

问题描述 投票:2回答:2

背景

请考虑以下最小示例:

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

import time

time.sleep(5)
raise Exception

睡眠五秒后代码会引发错误,留下以下追溯。

Traceback(最近一次调用最后一次): 在<module>中的文件“test / minimal_error.py”,第4行 提高例外 例外

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

import time

time.sleep(5)
a = 1
raise Exception

在python解释器从睡眠状态唤醒并到达下一行raise Exception之后,它将引发错误,但它会留下以下追溯。

Traceback(最近一次调用最后一次): 在<module>中的文件“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中发生的事情。)

python interpreter
2个回答
5
投票

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

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

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


0
投票

我认为这是一个经典的问题,描述here

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

© www.soinside.com 2019 - 2024. All rights reserved.