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

标签 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'

为什么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/

相关文章:

通过 malloc 和 getchar() 创建字符串

python - Binning into timeslots - 有没有比使用 list comp 更好的方法?

python - Django 动态表单集 UpdateView 不更新

python - 迭代 pandas 数据框中的行并应用 lambda 函数

C - If (No File Found) { 使用标准输入 }

c - 使用 read() 从 stdin 读取\n

php - 如何使用 php 命令行在一行中获取多个标准输入

C-运行程序接受输入

python - 来自 Firefox bookmark.html 源代码的 YouTube video_id [几乎存在]

python - 使用 Perl 或 Python 将日志文件内容导入 MySQL 数据库