On Sat, Feb 12, 2011 at 7:25 PM, Peter Otten <__pete...@web.de> wrote:
> 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.

Cool, thanks.

I read here: http://docs.python.org/reference/datamodel.html about the
func_globals and how it is a read only attribute. I incorrectly
thought that this dictionary was read only because the reference was
read only.


>
> Peter
> --
> http://mail.python.org/mailman/listinfo/python-list
>
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to