为什么Python在打印回溯时读取当前目录? $echo“您的代码不好,您应该感觉不好”>“ $python Python 3.6.0(默认,2016年12月28日,19:53:26) linux上的[GCC 4.8.5 20150623(Red Hat 4.8.5-11)] 有关详细信息,请键入“帮助”、“版权”、“信用证”或“许可证”。 >>> 2 + '2' 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 你的代码不好,你应该感到不好 TypeError:不支持+:“int”和“str”的操作数类型

为什么Python在打印回溯时读取当前目录? $echo“您的代码不好,您应该感觉不好”>“ $python Python 3.6.0(默认,2016年12月28日,19:53:26) linux上的[GCC 4.8.5 20150623(Red Hat 4.8.5-11)] 有关详细信息,请键入“帮助”、“版权”、“信用证”或“许可证”。 >>> 2 + '2' 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 你的代码不好,你应该感到不好 TypeError:不支持+:“int”和“str”的操作数类型,python,stdin,Python,Stdin,为什么Python会将字符串“与匹配该文件名的文件混淆?如果Python遇到未处理的异常,我不希望它尝试从我的磁盘读取任何文件 您还可以使用“”文件名获取它: $ echo "Your code is bad and you should feel bad" > "<stdin>" $ python Python 3.6.0 (default, Dec 28 2016, 19:53:26) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on

为什么Python会将字符串
与匹配该文件名的文件混淆?如果Python遇到未处理的异常,我不希望它尝试从我的磁盘读取任何文件

您还可以使用
“”
文件名获取它:

$ echo "Your code is bad and you should feel bad" > "<stdin>"
$ python
Python 3.6.0 (default, Dec 28 2016, 19:53:26) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 2 + '2'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    Your code is bad and you should feel bad
TypeError: unsupported operand type(s) for +: 'int' and 'str'
$echo“渴望峡湾”>“
$python-c'wat'
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
渴望峡湾
NameError:未定义名称“wat”

有没有办法防止这种行为,或者是将其硬编码到REPL中

Python不跟踪源代码与任何编译字节码的对应关系。在需要打印回溯之前,它甚至可能不会读取源代码,例如,如果模块是从
.pyc
文件加载的

当Python需要打印回溯时,它会尝试查找与所涉及的所有堆栈帧对应的源代码。在堆栈跟踪中看到的文件名和行号都是Python必须使用的。如果使用的是
回溯
模块,代码路径将通过
linecache
中的一个部分,但是默认的
sys.excepthook
不会通过该路径

通过本机调用PyErr_Display,最终使用显示单个源代码行
\u Py\u DisplaySourceLine
无条件地尝试在当前工作目录中查找文件(出于某种原因-被误导的优化?),然后调用
\u Py\u FindSourceFile
来搜索
sys.path
,如果工作目录没有匹配该名称的文件。通常,它找不到
文件,当它找不到文件时,它只会跳过打印源代码,但如果它找到了,它会从该文件打印

我最初认为可以通过将Python运行在隔离模式下来防止这种情况。隔离模式的效果之一是从
sys.path
中删除脚本的目录。实验证明,这并没有改变什么,也就是当我意识到无论发生什么情况,
\u Py\u DisplaySourceLine
都会尝试工作目录时


通过在本机代码路径中排除
文件名来解决这个问题相当简单,就像
linecache
那样。无条件搜索当前目录中文件的代码也应该更改。

哦,这是一个可爱的bug。您应该报告它。在查找更新linecache(
linecache.updatecache()
)时,它已经使用了特殊情况
filename.startswith(“”
),因此添加类似于checkcache()的内容不是不可能的。@pbuck:Huh,确实如此。不过,我认为这个代码路径实际上没有经过
linecache
(还有吗?)<当我在Python 3上尝试时,sys.modules中的code>'linecache'会在未捕获异常前后报告
False
。使用
-I
标志运行会防止
sys.path[0]
中出现空字符串,但这不会改变从中回溯读取的行为disk@wim你似乎是对的。我本以为这会起作用,但似乎我误读了中的一行,该行尝试在当前工作目录中查找文件,而不考虑当前目录是否在路径上。
$ echo "pining for the fjords" > "<string>"
$ python -c 'wat'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
    pining for the fjords
NameError: name 'wat' is not defined