导入错误:无法导入名称 NO_DEFAULT
我正在尝试运行一个Django网站的manage.py
脚本,但它出现了以下错误:
Traceback (most recent call last):
File "manage.py", line 2, in <module>
from django.core.management import execute_manager
File "/scratch/tools/lib/python2.5/site-packages/django/core/management/__init__.py", line 4, in <module>
from optparse import OptionParser, NO_DEFAULT
ImportError: cannot import name NO_DEFAULT
无论我使用的是Python 2.5.1还是2.6.1(Fedora的版本),这个问题都会发生。我在交互式的Python会话中进行导入时也能重现这个错误。
这并不让人感到意外,因为NO_DEFAULT
并没有在optparse.py
的__all__
中列出,也没有在optparse
的文档中找到。
让我感到惊讶的是,在我自己的工作站上,我可以在Python 2.5.5和2.6.6(Debian的版本)中成功执行from optparse import NO_DEFAULT
。
我有两个问题:
- 为什么我可以导入一个没有在
__all__
中列出的东西? - 我该如何修复Django的
manage.py
?我希望它能在Python 2.5中正常工作,如果可能的话。
1 个回答
在Python中,__all__
更像是一个建议,而不是硬性规定。它的出现是因为我们对*-import
这种导入方式又爱又恨。在文档中,这种方式被描述为:
如果用星号('*')替换标识符列表,模块中定义的所有公共名称都会被绑定到
import
语句的本地命名空间中。
这里有一个技术上的难题:解释器应该怎么知道一个模块的公共名称是什么呢?通常的约定是,模块中不以_
开头的名称就是公共的;你可能会认为,作为初步的做法,应该简单地导入模块命名空间中的所有这些名称。但不幸的是,当你引入包时,这就变得复杂了,因为计算公共名称需要处理各种导入、路径重写、文件读取等等。这可不是件好事。因此,模块作者可以通过在模块中定义__all__
,来明确指定哪些名称应该被*-import
导入。
但是,如果你不使用*-import
,而是直接给解释器你想导入的变量名,那么它就不需要担心找到所有的全局名称,因此可以忽略__all__
,直接在模块的命名空间中查找这个名称。
这意味着__all__
可能和locals().keys()
中不以下划线开头的名称集合不一样。特别是,模块中可能有一些完全正常的对象并不会通过*-import
导出。这就是NO_DEFAULT
的情况。