为什么token.py的存在会导致内置help()失效?
作为一个爱好者和学习项目,我正在用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 个回答
你可以在这里查找问题并报告新的问题:http://bugs.python.org/。
问题在于,你本地的 token.py
文件被 help()
函数导入了,而不是 Python 自带的 token.py
。这种情况会发生在任何与内置模块名字重复的 .py
文件上。例如,你可以在当前工作目录下创建一个 pydoc.py
文件,然后在 Python 中使用 help()
。help()
函数是 Python 自带的一个功能,所以它的导入路径和其他 Python 代码是一样的。