为什么token.py的存在会导致内置help()失效?

2 投票
4 回答
581 浏览
提问于 2025-04-15 18:21

作为一个爱好者和学习项目,我正在用Python写一个解析器生成器。其中一个代码文件叫“token.py”,里面有几个类,用来把普通字符串转换成Token对象。我刚发现,如果在一个包含“token.py”的目录中使用Python控制台的“help()”函数,就会出现错误。

下面是重现这个错误的方法。创建一个新目录,并添加以下文件:

/New Folder
  main.py
  token.py

把'token.py'留空。在main.py中,写一个简单的函数,比如:

def test():
    pass

然后,在你的Python控制台中,导入'main'并调用'help(main.test)',你会看到这样的结果:

C:\New Folder>python
Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import main
>>> help(main.test)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python31\lib\site.py", line 428, in __call__
    import pydoc
  File "C:\Python31\lib\pydoc.py", line 55, in <module>
    import sys, imp, os, re, inspect, builtins, pkgutil
  File "C:\Python31\lib\inspect.py", line 40, in <module>
    import tokenize
  File "C:\Python31\lib\tokenize.py", line 37, in <module>
    COMMENT = N_TOKENS
NameError: name 'N_TOKENS' is not defined
>>>

如果你删除'token.py'文件,help()就会正常工作。这种情况在Python 3.1和Python 2.5中都有出现。

这是一个已知的问题吗?如果不是,我该如何报告这个问题?

编辑:

有几个评论提到,这种行为并不是一个bug。定义“help”的模块会从Python的标准库中导入一个叫“token”的模块。然而,Python在查找模块时,会先在应用程序文件夹中查找,然后再去库中找。在上面的例子中,“help”试图使用我的“token.py”,而不是Python自带的那个,这就导致了错误。

既然Python被定义为这样工作,我想这不是一个bug。但为什么人们觉得这种行为是可以接受的呢?这意味着即使不改变现有模块,向Python的库中添加新模块也可能会破坏现有的应用程序。这还意味着程序员应该记住Python库中所有模块的名字——这和让程序员记住.NET或Java中的每个命名空间有什么区别呢?为什么Python应用程序不能有自己的命名空间?为什么Python标准库的模块没有自己的命名空间呢?

4 个回答

1

你可以在这里查找问题并报告新的问题:http://bugs.python.org/

4

当你给自己的模块起名字时,如果这个名字和Python标准库里的模块名字很像,那你就要对可能出现的后果负责了。因为其他的Python标准库模块可能会依赖于你所隐藏或覆盖的那些模块。如果你的模块没有很好地模仿你隐藏的模块的功能,那问题不是出在Python上,而是出在你的代码上。当然,这个道理适用于模块token,也适用于其他模块。

如果你是无意中遇到这个问题,并且想找个方法来检查你的代码,看看有没有可能的错误或不太靠谱的写法(而不是像你说的那样,想报告Python标准库里不存在的bug),我觉得像pylint这样的工具可能会对你有帮助。

6

问题在于,你本地的 token.py 文件被 help() 函数导入了,而不是 Python 自带的 token.py。这种情况会发生在任何与内置模块名字重复的 .py 文件上。例如,你可以在当前工作目录下创建一个 pydoc.py 文件,然后在 Python 中使用 help()help() 函数是 Python 自带的一个功能,所以它的导入路径和其他 Python 代码是一样的。

撰写回答