What is an alternative to execfile in Python 3?
What is an alternative to execfile in Python 3?
According to the documentation, instead of
execfile(./filename)
Use
exec(open(./filename).read())
See:
You are just supposed to read the file and exec the code yourself. 2to3 current replaces
execfile(somefile.py, global_vars, local_vars)
as
with open(somefile.py) as f:
code = compile(f.read(), somefile.py, exec)
exec(code, global_vars, local_vars)
(The compile call isnt strictly needed, but it associates the filename with the code object making debugging a little easier.)
See:
- http://docs.python.org/release/2.7.3/library/functions.html#execfile
- http://docs.python.org/release/3.2.3/library/functions.html#compile
- http://docs.python.org/release/3.2.3/library/functions.html#exec
What is an alternative to execfile in Python 3?
While exec(open(filename).read())
is often given as an alternative to execfile(filename)
, it misses important details that execfile
supported.
The following function for Python3.x is as close as I could get to having the same behavior as executing a file directly. That matches running python /path/to/somefile.py
.
def execfile(filepath, globals=None, locals=None):
if globals is None:
globals = {}
globals.update({
__file__: filepath,
__name__: __main__,
})
with open(filepath, rb) as file:
exec(compile(file.read(), filepath, exec), globals, locals)
# execute the file
execfile(/path/to/somefile.py)
Notes:
-
Uses binary reading to avoid encoding issues
-
Guaranteed to close the file (Python3.x warns about this)
-
Defines
__main__
, some scripts depend on this to check if they are loading as a module or not for eg.if __name__ == __main__
-
Setting
__file__
is nicer for exception messages and some scripts use__file__
to get the paths of other files relative to them. -
Takes optional globals & locals arguments, modifying them in-place as
execfile
does – so you can access any variables defined by reading back the variables after running. -
Unlike Python2s
execfile
this does not modify the current namespace by default. For that you have to explicitly pass inglobals()
&locals()
.