Covich
Covich

Reputation: 2814

exec a global variable from an extern module

I have an extern module where I want to set "exec" expressions as global (because I need to pass strings as variables names)

So, I have a function like

def fct_in_extern_module():
    exec 'A = 42' in globals()
    return None

and in my main script I have

import extern_module
extern_module.fct_in_extern_module()

Thus, why do I have

NameError: name 'A' is not defined

While if I do (in the main script)

def fct_in_main():
    exec 'B = 42' in globals()

fct_in_main()

>>> B
42

Any idea how can I set the string 'A' as a variable name in a extern module ?

Thanks !

Upvotes: 2

Views: 154

Answers (2)

mgilson
mgilson

Reputation: 310097

globals() always returns the __dict__ of the module where it was called. This is really the only reasonable choice ... consider:

# qux.py
import foo
foo.bar()

# foo.py
import baz
def bar():
    return baz.exec_stuff()

# baz.py
def exec_stuff():
    exec 'A = 1' in globals()

Should the global be set in qux.py or foo.py or baz.py? Looking at it this way, baz is the most obvious choice and the one that python uses.

Now that brings us to the question of why are you using exec in the first place? Generally it's a much better idea to return the value you need to the caller. Then they can do what they wish with it:

def fn_in_extern_module():
    return 42

and then:

import extern
A = extern.fn_in_extern_module()

Upvotes: 1

Alex Martelli
Alex Martelli

Reputation: 882421

globals() means "the globals dict of this module". Thus, the way you have chosen to code extern_module.py will not affect the globals dict of any other module.

One way to fix: define it as:

def fct_in_extern_module(where):
    exec 'A = 42' in where

and call it as:

extern_module.fct_in_extern_module(globals())

Of course, as usual, exec is not the best way to solve the problem. Better:

def fct_in_extern_module(where):
    where['A'] = 42

faster and cleaner.

Upvotes: 4

Related Questions