我希望防止from module import *语句导入模块中的某些名称,以减少名称空间的混乱。(如果设计不好,请告诉我。)
下面是我想要的行为(以os和posix为例):
import os应该使os.posix可用。from os import *不应使posix可用。from os import posix是否会导致错误。导入模块module中的代码可以检测它是用import module还是from module import *导入的吗?
发布于 2013-10-11 00:13:52
是否可以让导入模块中的代码检测它是与导入模块一起导入的,还是从模块导入*导入的?
是的,至少在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')那么,既然你有了这些信息,你能用它做什么呢?在posix的情况下不导入IMPORT_STAR?没有它你的模块还能工作吗?
最重要的是,请记住模块可以--而且经常是--多次导入。如果一个模块用import foo导入您,而另一个模块稍后导入from foo import *,那么您想要发生什么?而且,即使你有答案,你怎么可能这样做,因为你的模块代码只能在第一次运行?它将不得不看到未来,以检测到其他人将在以后的from foo import *。
发布于 2013-10-10 23:54:02
我不太明白这个问题。当另一个模块导入时,您可以影响从模块中导入哪些名称。这里有一个简单的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 *的成语确实应该尽量避免。它增加了模拟和测试的难度,它还引入了对象来源的模糊性,除了前面提到的命名空间冲突之外,还使得代码更难读取。
https://stackoverflow.com/questions/19308062
复制相似问题