$ 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'
为什么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
有什么方法可以防止这种行为,或者它是否被硬编码到 REPL 中?
最佳答案
Python 不会跟踪哪些源代码对应于任何已编译的字节码。在需要打印回溯之前,它甚至可能不会读取该源代码,例如,如果模块是从 .pyc
加载的文件。
当 Python 需要打印回溯时,也就是它试图找到与所有涉及的堆栈帧对应的源代码的时候。你在堆栈跟踪中看到的文件名和行号都是 Python 必须继续的。如果它使用 traceback
模块,代码路径将通过 linecache
中的一个部分那excludes filenames starting and ending with <
and >
, 但默认 sys.excepthook
不会经过那条路。
default sys.excepthook
通过 native 调用 PyErr_Display
,最终使用 _Py_DisplaySourceLine
结束显示单独的源代码行。 _Py_DisplaySourceLine
无条件地尝试在当前工作目录中查找文件(出于某种原因 - 错误的优化?),然后调用 _Py_FindSourceFile
搜索sys.path
如果工作目录没有匹配该名称的文件。通常,它不会找到 <stdin>
或 <string>
文件,它会在找不到文件时跳过打印源代码,但如果找到一个文件,它会从该文件打印。
我最初认为您可以通过使用 -I
flag 运行 Python 来防止这种情况发生,将其置于隔离模式。隔离模式的影响之一是从 sys.path
中删除脚本的目录。 .实验证明这并没有改变什么,这就是我意识到 _Py_DisplaySourceLine
的时候无论如何都会尝试工作目录。
通过排除 <>
来解决这个问题会相当简单 native 代码路径中的文件名,例如 linecache
做。无条件在当前目录搜索文件的代码也要改。
关于python - 为什么 Python 在打印回溯时从当前目录读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43593899/