executing a function with feeding its global variables
Peter Otten
__peter__ at web.de
Sat Feb 12 13:25:31 EST 2011
Jean-Daniel wrote:
> Hello,
>
> I am writing a small framework where the user which writes a function
> can expect some global variable to be set in the function namespace.
>
> The user has to write a function like this:
> """
> # function.py
> from framework import, command, run
>
> @command
> def myfunc():
> print HOST
>
> if __name__=="__main__":
> run()
> """
>
> command() registers the function, and run() evaluates or execute the
> function within an environment or a namespace where HOST has been
> automagically set.
>
> Question: how can write run in a way that when using run() in a
> script, the decorated function will be run with the special names made
> available?
>
> Here is the code for this, which does not work as intended because the
> 'HOST' can not be found when evaluating the decorated function
>
> """
> # framework.py
> HOST = '192.168.0.1'
> PORT = 12345
>
> commands = []
>
> def command(f):
> commands.append(f)
> return f
>
> def run():
> for f in commands:
> assert globals()['HOST']
> exec 'f()' in globals(),locals()
>
> if __name__=='__main__':
>
> @command
> def info():
> print HOST,PORT
>
> run()
> """
>
> Note that the assert makes sure the HOST variable is indeed present in
> the globals when running the function. When running function.py, I get
> an NameError exception. When I put the func function in the framework
> module and execute framework.py as a script, this works fine, the
> global HOST is available in the func namespace which gets printed. I
> tried many combinations of eval() or exec as well as many combinations
> for the globals() and locals() mapping fed to eval/exec without
> success.
Every module has its own global namespace, and a function is looking for
global variables in the namespace it is defined in, not the one where the
function is called from. A function defined in Python carries its global
namespace with it as the __globals__ attribute (func_globals in older Python
versions).
def run():
for f in commands:
f.__globals__.update(HOST=HOST, PORT=PORT)
f()
Note that every function in the function's module will see the extra
variables.
Peter
More information about the Python-list
mailing list