导入错误:无法导入名称 NO_DEFAULT

发布于 2024-11-24 10:31:14 字数 1002 浏览 2 评论 0原文

我正在尝试运行 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 一起使用。

I'm trying to run a Django site's manage.py script, but it fails with the following error:

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

This happens regardless of whether I use Python 2.5.1 or 2.6.1 (Fedora packages). I can reproduce the error when doing the import in an interactive Python session.

This is not very surprising, considering that NO_DEFAULT is not listed in optparse.py's __all__ and is also not listed in the optparse documentation.

What is surprising, then, is that on my own workstation I can successfully do from optparse import NO_DEFAULT in both Python 2.5.5 and 2.6.6 (Debian packages).

My question is twofold:

  • How can it be that I can import something that is not listed in __all__?
  • How should I fix the Django manage.py? I want it to work with Python 2.5, if at all possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

腹黑女流氓 2024-12-01 10:31:14

与 Python 中一样,__all__ 与其说是规则,不如说是指南。它的出现是因为我们对它又爱又恨的*-import,在文档

如果标识符列表被星号('*')替换,则所有公共
模块中定义的名称绑定在模块的本地命名空间中
导入语句。

这里有一个直接的技术困难:解释器应该如何知道模块的公共名称是什么?有一个约定,模块中任何不以 _ 开头的名称都是公共的;您可能认为作为第一个近似,应该简单地将所有此类名称导入模块的名称空间中。不幸的是,当您引入包时,这会变得更加复杂,因为计算公共名称将成为一项艰巨的任务,涉及各种导入、路径重写、文件读取等。这不是什么好事。因此,采取了简化的决定,允许模块作者通过在模块中定义 __all__ 来准确指定应从 *-import 导入包中的哪些名称。

但是如果你不*-import——如果你给解释器你想要导入的变量的名称——那么它就不需要担心找到所有的全局名称,所以它可以忽略__all__ 并只需在模块的命名空间中查找名称即可。

这确实意味着 __all__ 可能与不以下划线开头的 locals().keys() 子集不同。特别是,模块中可能存在完美的对象,但没有通过 *-imports 导出。这就是 NO_DEFAULT 所发生的情况。

As always in Python, __all__ is more of a guideline than a rule. It comes about because of the we-love-to-hate-it *-import, described in the docs as

If the list of identifiers is replaced by a star ('*'), all public
names defined in the module are bound in the local namespace of the
import statement.

There is an immediate technical difficulty here: how should the interpreter know what the public names of a module are? There is a convention that any name in a module not beginning with an _ is public; you might think that as a first approximation one should simply import all such names in the module's namespace. Unfortunately, this becomes more complicated when you introduce packages, because then computing the public names becomes a large task involving various imports, path rewrites, file reads, and what have you. This is not a good thing. Thus, the simplifying decision was taken to allow the module author to specify exactly which names in the package should be imported from a *-import, by defining __all__ in the module.

But if you don't *-import -- if you give the interpreter the name of the variable you want to import -- then it doesn't need to worry about finding all the global names, so it can ignore __all__ and just look up the name in the module's namespace.

That does mean that __all__ may not be the same as the subset of locals().keys() not starting with an underscore. In particular, there may be perfectly good objects in the module which are not exported by *-imports. This is what happens with NO_DEFAULT.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文