72

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?

0

4 Answers 4

83

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.

Sign up to request clarification or add additional context in comments.

20 Comments

Why is this better than Lennart's version?
@SvenMarnach, if you can post a link to official recommendation or source code (so that people can be sure it won't be "fixed" in future), I'd give it a +1. =)
@kenorb: It does work in Python 3.4. You apparently tried to use the last line without replacing locals and globals with whatever you want to have there instead. They are just placeholders, I can't know what you want to pass in, or whether you want to omit them altogether. I consider this the "official" recommendation because this is how the "official" 2to3 tool migrates execfile() calls.
@vinaygarg These are dictionaries with the global and lcoal variables the file is supposed to be executed within. You can omit them to execute the file in the current scope. A common alternative is to use exec(..., {}) to execute the file in a new temporary scope.
@AidasBendoraitis I used globals and locals as variable names here; I could just as well have used x and y or whatever. You usually wouldn't do exec(code, globals(), locals()), since this would be the same as just exec(code).
|
71
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.

14 Comments

Why is this better than Sven's version?
@Matt: It's simpler?
@VPeric: In Python 2.x, you need to use the exec ... in ... form of exec in such a situation. For example exec code in globals() will execute the code in the module's global namespace. Note that the exec'ed code can't change local variables in a way that is reliably visible by the nested function.
@VPeric: All of the stuff here works, if you have a specific problem, make it a question.
No, it will be closed when garbage collected, so it doesn't have to (although it's a good idea to close it).
|
9

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_file(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_file("/path/to/somefile.py")

2 Comments

i have this as the old version: execfile(join(dirname(file), 'ExcelLibrary', 'version.py')) so with the new.... exec(open(filename).read()) how does that become?
@tijnn it can't be done (easily) in a single line, that's why I've provided a function - exec_full
4

Standard runpy.run_path is an alternative.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.