0

我想防止from module import *语句导入模块内的某些名称,以减少命名空间混乱。(让我知道这是否是糟糕的设计。)

这是我想要的行为(以osposix为例):

  • import os应该os.posix提供。
  • from os import *不应该posix提供。
  • 我不在乎是否from os import posix会导致错误。

导入模块中的代码module是否可以检测它是否使用import moduleor导入from module import *

4

2 回答 2

9

我不确定我是否理解这个问题。当另一个模块导入它时,您可以影响将导入模块中的哪些名称。例如,这是一个简单的test模块:

__all__ = ['foo']

foo = 3
bar = 4

和一个交互式 python 会话:

>>> import test
>>> test.foo
3
>>> test.bar
4
>>> from test import *
>>> foo
3
>>> bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'bar' is not defined

请注意test.bar可用,但bar不是因为它未包含在__all__列表中。


最后,值得指出的是,这个from ... import *成语确实应该尽可能地避免。它使模拟和测试变得更加困难,除了您已经提到的命名空间冲突之外,它还引入了对象起源的模糊性,使代码更难阅读。

于 2013-10-10T23:54:02.457 回答
0

导入模块模块中的代码是否可以检测它是使用导入模块导入还是从模块导入 * 导入的?

是的,至少在 CPython 中是这样。但这不是一件很有用的事情,而且肯定不会解决你想解决的问题。正确的答案当然是使用__all__,正如 mgilson 所示。

但让我们说明为什么这是错误的答案。

首先,这是一种方法:

import sys
import opcode

f1 = sys._getframe(1)
op = f1.f_code[f1.f_lasti+3]
del f1
if op == opcode.opmap['IMPORT_FROM']:
    print('from me import something')
elif op == opcode.opmap['IMPORT_STAR']:
    print('from me import *')
elif op == opcode.opmap['STORE_NAME']:
    print('import me')

那么,既然你有了这些信息,你能用它做什么呢?不进口posixIMPORT_STAR情况下?没有它你的模块还能工作吗?

最重要的是,请记住,模块可以——并且经常被——多次导入。如果一个模块使用 导入您import foo,而另一个模块稍后导入from foo import *,您希望发生什么?而且,即使你有答案,你怎么可能做到这一点,因为你的模块代码只在第一次运行?它必须看到未来才能检测到其他人稍后会去from foo import *

于 2013-10-11T00:13:52.277 回答