Python:为什么要禁止'from <module> import *'?</module>

时间:2010-08-26 01:46:34

标签: python namespaces module

如果你碰巧有

from <module> import *

在你的程序(或模块)中间,你会收到警告:

/tmp/foo:100: SyntaxWarning: import * only allowed at module level

我理解为什么一般不鼓励import *(名称空间不可见), 但是在很多情况下它会很方便,特别是在哪里 代码不会与任何人共享。

所以,任何人都可以详细解释为什么from <module> import *应该详细解释 在所有可能的情况下都被禁止?

6 个答案:

答案 0 :(得分:22)

我相信“在您的程序中间”,您正在讨论导入内部函数定义:

def f():
    from module import *    # not allowed

这是不允许的,因为它会使函数体更难以优化。 Python实现想要在字节编译函数时知道函数局部变量的所有名称,以便它可以优化变量引用到(CPython)虚拟机的操作数堆栈上的操作,或至少到本地变量槽。操作而不是外部命名空间中的查找。如果您可以将模块的全部内容转储到函数的本地名称空间中,那么编译器必须假设函数中的任何名称可能引用模块全局,因为带来的名称列表in from module import *仅在运行时已知。

from module import * 置于顶级声明之间的风格很差,但允许这样做:

def f():
    ...

from module import *

def g():
    ...

编辑2013年4月:在研究其他内容时,我发现由于"Nested Scopes" featurePEP 227),这种限制是在Python 2.1中引入的。引用链接:

  

更改的一个副作用是from module import *exec语句在某些条件下在函数范围内被设为非法。 Python参考手册一直表示from module import *仅在模块的顶层是合法的,但CPython解释器以前从未强制执行过。作为嵌套作用域实现的一部分,将Python源转换为字节码的编译器必须生成不同的代码来访问包含作用域中的变量。 from module import *exec使编译器无法解决这个问题,因为它们将名称添加到本地命名空间,这在编译时是不可知的。因此,如果函数包含带有自由变量的函数定义或lambda表达式,编译器将通过引发SyntaxError异常来标记此函数。

这澄清了评论中讨论的Python 3.x vs 2.x行为。它总是与语言规范相反,但CPython 2.1到2.7只会在函数内发出from module import *的错误,如果它可能影响编译器知道变量是在本地绑定还是在包含范围内绑定的能力。在3.x中,它已被提升为无条件错误。

SON OF EDIT: ......显然,flashk几年前在另一个答案中指出了这一点,引用了同一段“Python 2.1中的新功能”。你们现在都要投票了。

答案 1 :(得分:16)

在任何词汇层面,from amodule import *是“当时似乎是一个好主意”的设计决策,已经证明在现实生活中真正的灾难,其中可能的例外在交互式解释器提示符(即使这样,我不是太热了 - import module as m强制只使用两个额外的字符来代替[[只是m.前缀]],限定名称总是比名字更清晰,更灵活,更不用说在mhelp(m)reload(m)可用的探索性互动情况下非常实用!)。

这种陷入困境的构造使得阅读代码的穷人(通常是注定要帮助调试它的代价)非常难以理解神秘出现的名字来自何处 - 如果构造被使用的话多于此曾经在词汇层面;但即使只使用一次,它也会强制重新阅读整个模块,每次都可以说服自己,是的,那个脏兮兮的名字必须来自模块。

另外,模块作者通常不会遇到“支持”有问题的可怕构造所需的极端麻烦。如果你的代码中有某个地方,比如你在模块的最顶层使用sys.argv(以及import sys),你如何知道那个sys是它应该是的模块......或者来自... import *的一些完全不同的模块(或非模块)?乘以你正在使用的所有合格的名字,痛苦是唯一的最终结果 - 那些需要长时间,费力的调试的神秘错误(通常在的人的不情愿的帮助下得到) “Python ......! - )。

在函数中,添加和覆盖任意本地名称的方法会更糟。作为一个基本但至关重要的优化,Python编译器会查看函数的主体,以查找每个裸名称上的任何赋值或其他绑定语句,并认为它们看到的那些名称是“本地”的(其他名称必须是全局或内置函数)。使用import *(就像使用exec somestring而没有明确的dicts用作命名空间一样),突然间它变成了一个完全神秘的名称是本地的,这些名称是全局的 - 所以糟糕的编译器将不得不为每个名称查找采用最慢的策略,使用局部变量的dict(而不是它通常使用的紧凑“矢量”),并为每个引用的裸名称执行最多三次dict查找,一遍又一遍。

转到任何Python交互式提示。输入import this。你看到了什么? Python的禅宗。那篇文章中最后也可能是最伟大的智慧是什么......?

  

命名空间是一个很棒的主意    - 让我们做更多的事情!

通过强制使用合格名称​​以及非常可取的姓名,你实际上是在做这个明智建议的相反:而不是欣赏伟大和尊重名称空间,并做更多这些,你分解两个非常好的和现成的命名空间(你导入的模块的命名空间,以及你的词法范围的命名空间)重新导入它来制造一个单一的,不圣洁的,有缺陷的,缓慢的,僵硬的,无法使用的混乱。

如果我可以返回并在Python中更改一个早期设计决策(这是一个很难的选择,因为def尤其是lambda用于Javascript这么多更可读的呼叫function紧随其后;-),我会追溯地消除Guido心中的import *想法。在交互式提示中,任何所谓方便探索的便利都可以平衡它所造成的邪恶数量......! - )

答案 2 :(得分:12)

release notes for Python 2.1似乎解释了为什么存在这种限制:

  

改变的一个副作用是   from module import *和exec   陈述已被宣布为非法   在某个功能范围内   条件。 Python参考   手册一直都说过   模块导入*仅适用于   顶级的模块,但CPython   口译员从未强制执行此操作   之前。作为实施的一部分   嵌套范围,编译器   将Python源代码转换为字节码   生成不同的代码来访问   包含范围中的变量。从   模块导入*和exec使它成为   编译器无法想象   这个,因为他们添加了名称   本地命名空间   在编译时不可知。因此,   如果函数包含函数   定义或lambda表达式   自由变量,编译器会标记   这是通过引发SyntaxError   异常。

答案 3 :(得分:4)

这不是禁止的,因为......

...它对于快速脚本和shell探索很方便。

...但您不应将其保留在任何严肃的代码中

  1. 它可能导致导入您不知道的名称并删除本地名称
  2. 你不知道你的代码中使用了什么,很难知道脚本依赖
  3. 代码完成将无法正常工作
  4. IDE方便检查,例如“此var尚未声明”无法再使用
  5. 更容易创建循环导入

答案 4 :(得分:1)

根本不被禁止。它工作正常,但你得到一个警告,因为它通常是一个坏主意(由于其他人已经进入的原因)。如果你愿意,你可以抑制警告;警告模块就是你想要的。

答案 5 :(得分:0)

其他人已经给出了深入的答案,我将简要回答一下我的理解..当你使用它时,你可以直接调用导入的模块中的任何函数,而无需执行modulename.functioname(你可以只调用“functionname”)这会产生问题,如果你在不同的模块中有2个相同名称的函数,并且在处理很多函数时也会产生混淆,因为你不知道它属于哪个对象/模块(从点开始)有人看着已编写的不熟悉的代码的视图)