为什么Python在打印回溯时会从当前目录中读取?

wim*_*wim 15 python stdin

$ 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'
Run Code Online (Sandbox Code Playgroud)

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

您也可以使用"<string>"文件名获取它:

$ 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
Run Code Online (Sandbox Code Playgroud)

有没有办法防止这种行为,还是硬编码到REPL中?

use*_*ica 8

Python不跟踪任何编译的字节码对应的源代码.它甚至可能不会读取该源代码,直到它需要打印回溯,例如,如果从.pyc文件加载模块.

当Python需要打印回溯时,就是当它试图找到与所涉及的所有堆栈帧相对应的源代码时.您在堆栈跟踪中看到的文件名和行号都是Python必须继续的.如果它正在使用traceback模块,代码路径将通过一个部分,linecache其中排除以<和开头和结尾的文件名>,但默认情况下sys.excepthook不会通过该路径.

所述默认sys.excepthook经过本地呼叫PyErr_Display,这最终卷起使用_Py_DisplaySourceLine显示单个源极线._Py_DisplaySourceLine无条件地尝试在当前工作目录中找到该文件(由于某种原因 - 错误的优化?),然后调用_Py_FindSourceFile以搜索sys.path与该名称匹配的文件(如果工作目录没有它).通常,它不会找到<stdin><string>文件,它只是在找不到文件时跳过打印源代码,但如果找到一个,则从该文件打印.

我最初认为你可以通过运行带有-I标志的 Python来防止这种情况,将其置于隔离模式.隔离模式的一个影响是从中删除脚本的目录sys.path.实验证明,这并没有改变事情,这是当我意识到_Py_DisplaySourceLine尝试工作目录时无论如何.

通过<>在本机代码路径中排除文件名来解决这个问题是非常简单的linecache.还应该更改无条件地在当前目录中搜索文件的代码.