Modules and variable scopes
<p>I'm not an expert at python, so bear with me while I try to understand the nuances of variable scopes.</p>

<p>As a simple example that describes the problem I'm facing, say I have the following three files.</p>

<p>The first file is outside_code.py. Due to certain restrictions I cannot modify this file. It must be taken as is. It contains some code that runs an eval at some point (yes, I know that eval is the spawn of satan but that's a discussion for a later day). For example, let's say that it contains the following lines of code:</p>

<pre><code>def eval_string(x):
    return eval(x)
</code></pre>

<p>The second file is a set of user defined functions. Let's call it functions.py. It contains some unknown number of function definitions, for example, let's say that functions.py contains one function, defined below:</p>

<pre><code>def foo(x):
    print("Your number is {}!".format(x))
</code></pre>

<p>Now I write a third file, let's call it main.py. Which contains the following code:</p>

<pre><code>import outside_code
from functions import *
outside_code.eval_string("foo(4)")
</code></pre>

<p>I import all of the function definitions from functions.py with a *, so they should be accessible by main.py without needing to do something like functions.foo(). I also import outside_code.py so I can access its core functionality, the code that contains an eval. Finally I call the function in outside_code.py, passing a string that is related to a function defined in functions.py.</p>

<p>In the simplified example, I want the code to print out "Your number is 4!". However, I get an error stating that 'foo' is not defined. This obviously means that the code in outside_code.py cannot access the same foo function that exists in main.py. So somehow I need to make foo accessible to it. Could anyone tell me exactly what the scope of foo currently is, and how I could extend it to cover the space that I actually want to use it in? What is the best way to solve my problem?</p>

<p>You'd have to add those names to the scope of <code>outside_code</code>. If <code>outside_code</code> is a regular Python module, you can do so directly:</p>

<pre><code>import outside_code
import functions

for name in getattr(functions, '__all__', (n for n in vars(functions) if not n[0] == '_')):
    setattr(outside_code, name, getattr(functions, name))
</code></pre>

<p>This takes all names <code>functions</code> exports (which you'd import with <code>from functions import *</code>) and adds a reference to the corresponding object to <code>outside_code</code> so that <code>eval()</code> inside <code>outside_code.eval_string()</code> can find them.</p>

<p>You could use the <a href="https://docs.python.org/2/library/ast.html#ast.parse" rel="nofollow"><code>ast.parse()</code> function</a> to produce a parse tree from the expression before passing it to <code>eval_function()</code> and then extract all global names from the expression and only add <em>those</em> names to <code>outside_code</code> to limit the damage, so to speak, but you'd still be clobbering the other module namespace to make this work.</p>

<p>Mind you, this is almost as evil as using <code>eval()</code> in the first place, but it's your only choice if you can't tell <code>eval()</code> in that other module to take a namespace parameter. That's because <em>by default</em>, <code>eval()</code> uses the global namespace of the module it is run in as the namespace.</p>

<p>If, however, your <code>eval_string()</code> function actually accepts more parameters, look for a namespace or <code>globals</code> option. If that exists, the function probably looks more like this:</p>

<pre><code>def eval_string(x, namespace=None):
    return eval(x, globals=namespace)
</code></pre>

<p>after which you could just do:</p>

<pre><code>outside_code.eval_string('foo(4)', vars(functions))
</code></pre>

<p>where <code>vars(functions)</code> gives you the namespace of the <code>functions</code> module.</p>

python python-3.x