为什么有时不能使用from <module> import *?
假设我有一个Python模块,里面有很多函数,像这样:
#funcs.py
def foo() :
print "foo!"
def bar() :
print "bar!"
然后我还有另一个模块,它的功能是从字符串中解析出函数列表并运行这些函数:
#parser.py
from funcs import *
def execute(command):
command = command.split()
for c in command:
function = globals()[c]
function()
接着我可以打开Python,做以下操作:
>>> import parser
>>> parser.execute("foo bar bar foo")
foo!
bar!
bar!
foo!
我想在funcs.py
里添加一个方便的函数,这个函数可以让一系列函数像一个函数一样被调用:
#funcs.py (new version)
import parser
def foo() :
print "foo!"
def bar() :
print "bar!"
def parse(commands="foo foo") :
parser.execute(commands)
现在我可以从解析器本身递归地解析:
>>> import parser
>>> parser.execute("parse")
foo!
foo!
>>> parser.execute("parse bar parse")
foo!
foo!
bar!
foo!
foo!
但是出于某种原因,我不能直接从funcs
运行parse
,因为我遇到了一个键错误:
>>> import funcs
>>> funcs.parse("foo bar")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "funcs.py", line 11, in parse
parser.execute(commands)
File "parser.py", line 6, in execute
function = globals()[c]
KeyError: 'foo'
所以尽管foo
应该通过from funcs import *
这一行被导入到parser.py
中,但当我通过funcs.py
使用它时,在parser.py
的globals()
中找不到foo
。这怎么会发生呢?
最后我应该指出,如果先导入parser
再导入funcs
(但只能按这个顺序),就能正常工作:
>>> import parser
>>> import funcs
>>> funcs.parse("foo bar")
foo!
bar!
3 个回答
你的“解析器”其实不是个好主意。
不如这样做。
def execute(*functions):
for function in functions:
function()
然后你可以打开python,做以下操作:
>>> import parser
>>> from funcs import foo, bar
>>> parser.execute(foo, bar, bar, foo)
不使用“字符串”会让生活变得简单,因为你真正想要的其实就是函数本身。
- 在你导入解析器(parser)之后,打印一下全局变量,看看它做了什么。
parser
是一个内置模块。通常情况下,内置的解析器应该是加载系统自带的,而不是你自己写的。建议你换个名字,这样就不会出现问题了。- 你在导入函数,但解析器却从函数中导入了所有内容?
我建议你仔细考虑一下导入模块的顺序,以及你在哪些地方需要这些模块。
import module_name
和 from module_name import *
的作用是完全不同的。
前者会创建一个全局变量,名字叫 module_name
,它的类型是 module
,里面包含了这个模块的所有名字,你可以通过属性来访问这些名字。而后者则是为 module_name
里面的每一个名字都创建一个全局变量,但不会为 module_name
本身创建。
所以,当你使用 import funcs
时,foo
和 bar
并不会被放到 globals()
里面,因此当 execute
去查找它们时找不到。
像这样的循环依赖(比如 parser
想从 funcs
中导入名字,而 funcs
也导入 parser
)是很糟糕的。明确的比隐含的要好。不要试图制造这么多复杂的东西。直接告诉 parse()
有哪些函数可用。