62
votes

Python 2 had the builtin function execfile, which was removed in Python 3.0. This question discusses alternatives for Python 3.0, but some considerable changes have been made since Python 3.0.

What is the best alternative to execfile for Python 3.2, and future Python 3.x versions?

4

4 Answers

74
votes

The 2to3 script replaces

execfile(filename, globals, locals)

by

exec(compile(open(filename, "rb").read(), filename, 'exec'), globals, locals)

This seems to be the official recommendation. You may want to use a with block to ensure that the file is promptly closed again:

with open(filename, "rb") as source_file:
    code = compile(source_file.read(), filename, "exec")
exec(code, globals, locals)

You can omit the globals and locals arguments to execute the file in the current scope, or use exec(code, {}) to use a new temporary dictionary as both the globals and locals dictionary, effectively executing the file in a new temporary scope.

61
votes
execfile(filename)

can be replaced with

exec(open(filename).read())

which works in all versions of Python

Newer versions of Python will warn you that you didn't close that file, so then you can do this is you want to get rid of that warning:

with open(filename) as infile:
    exec(infile.read())

But really, if you care about closing files, you should care enough to not use exec in the first place.

9
votes

In Python3.x this is the closest thing I could come up with to executing a file directly, that matches running python /path/to/somefile.py.

Notes:

  • Uses binary reading to avoid encoding issues
  • Garenteed 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.
def exec_full(filepath):
    global_namespace = {
        "__file__": filepath,
        "__name__": "__main__",
    }
    with open(filepath, 'rb') as file:
        exec(compile(file.read(), filepath, 'exec'), global_namespace)

# Execute the file.
exec_full("/path/to/somefile.py")
3
votes

Standard runpy.run_path is an alternative.