executing a function with feeding its global variables

Peter Otten __peter__ at web.de
Sat Feb 12 19:25:31 CET 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