exec takes dictionaries to hold the global and local variables in the executed code. Pass in globals() to use the globals of the module it's in.
exec(open(file).read(), globals())
SSince you need to be able to call this from other modules, you can write runPyFile so it accepts a globals dictionary passed by the caller. Then the caller passes its globals().
def runPyFile(file, globals):
exec(open(file).read(), globals)
runPyFile(myFile, globals())
With a little stack inspection you can get the caller's globals without passing them in explicitly. This is "magic" and relies on details specific to CPython, so use with caution. (The caller can still pass in its own globals if it wants to.)
from inspect import currentframe
def runPyFile(file, globals=None):
if globals is None:
globals = currentframe().f_back.f_globals
exec(open(file).read(), globals)
Finally, there's the technique of just using your own dictionary rather than the module's global namespace. This isolates the execed code's variables from any module's and allows you to avoid overwriting values and even classes and functions in your module. You can make a dict subclass that lets you access elements as attributes to make it easier to get to those variables.
from inspect import currentframe
class Variables(dict):
__getattr__ = dict.__getitem__
def runPyFile(file, globals=None):
if globals is None:
globals = Variables()
exec(open(file).read(), globals)
return globals
vars = runPyFile(myFile)
print(vars.a) # `a` defined in myFile
vars.func(...) # calls `func` defined in myFile
importmechanism rather than usingexecto run other files.importlibfrom myFile import *instead ofrunPyFile(myFile)? Importing a module already executes it.