Reputation: 7701
If I have a python module that has a bunch of functions, say like this:
#funcs.py
def foo() :
print "foo!"
def bar() :
print "bar!"
And I have another module that is designed to parse a list of functions from a string and run those functions:
#parser.py
from funcs import *
def execute(command):
command = command.split()
for c in command:
function = globals()[c]
function()
Then I can open up python and do the following:
>>> import parser
>>> parser.execute("foo bar bar foo")
foo!
bar!
bar!
foo!
I want to add a convenience function to funcs.py
that allows a list of functions to be called as a function itself:
#funcs.py (new version)
import parser
def foo() :
print "foo!"
def bar() :
print "bar!"
def parse(commands="foo foo") :
parser.execute(commands)
Now I can recursively parse from the parser itself:
>>> import parser
>>> parser.execute("parse")
foo!
foo!
>>> parser.execute("parse bar parse")
foo!
foo!
bar!
foo!
foo!
But for some reason I can't just run parse
from funcs
, as I get a key error:
>>> 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'
So even though foo
should be imported into parser.py
through the from funcs import *
line, I'm not finding foo
in the globals()
of parser.py
when it is used through funcs.py
. How could this happen?
I should finally point out that importing parser
and then funcs
(but only in that order) allows it to work as expected:
>>> import parser
>>> import funcs
>>> funcs.parse("foo bar")
foo!
bar!
Upvotes: 0
Views: 2102
Reputation: 391852
Your "parser" is a pretty bad idea.
Do this instead.
def execute(*functions):
for function in functions:
function()
Then you can open up python and do the following:
>>> import parser
>>> from funcs import foo, bar
>>> parser.execute(foo, bar, bar, foo)
Life will be simpler without using "strings" where the function itself is what you really meant.
Upvotes: 0
Reputation: 9005
parser
is it built-in module also. Usually the built-in parser should load not yours.
I would change the name so you do not have problems.I would think carefully about what order you are importing modules and where you need them.
Upvotes: 0
Reputation: 61526
import module_name
does something fundamentally different from what from module_name import *
does.
The former creates a global named module_name
, which is of type module
and which contains the module's names, accessed as attributes. The latter creates a global for each of those names within module_name
, but not for module_name
itself.
Thus, when you import funcs
, foo
and bar
are not put into globals()
, and therefore are not found when execute
looks for them.
Cyclic dependencies like this (trying to have parser
import names from funcs
while funcs
also imports parser
) are bad. Explicit is better than implicit. Don't try to create this much magic. Tell parse()
what functions are available.
Upvotes: 2