Question

I have a config.py script that has PREAMBLE information. I can use execfile() function to read the contents of the configuration file.

execfile("config.py")
print PREAMBLE
>>> "ABC"

However, when execfile() is called in a method, I have an error.

def a():
    execfile("config.py")
    print PREAMBLE

a()
>>> NameError: "global name 'PREAMBLE' is not defined"

What's wrong and how to solve this issue?

Was it helpful?

Solution

You need to pass the global dictionary to execfile to achieve the same result:

def a():
    execfile("config.py",globals())
    print PREAMBLE

a()
>>> "some string"

If you don't want to pollute your global namespace, you can pass a local dictionary and use that:

def a():
    config = dict()
    execfile('/tmp/file',config)
    print config['PREAMBLE']

a()
>>> "some string"

For reference, in both cases above, /tmp/file contained PREAMBLE = "some string".

OTHER TIPS

The issue here is the namespaces in which the code runs when execfile() is called. If you study the documentation you will see that execfile() can take two namespace arguments to represent the global and the local namespaces for execution of the code.

At module level (i.e. when the execfile() call does not come from inside a function) then the module global namespace is used for both those namespaces. From inside a function the module globals are used as the global namespace and the local namespace is the function call namespace (which typically disappears when the call returns).

Consequently, since assignments preferentially bind names in the local namespace, executing the file sets up PREAMBLE inside the function call namespace, and so it can't be found at module level.

If your config files really are Python, wouldn't it be possible just to import them, or is there some organizational reason why that won't work? That way you could just import config and then refer to config.PREAMBLE in your code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top