classification
Title: execfile fixer produces code that does not close the file
Type: behavior Stage:
Components: 2to3 (2.x to 3.x conversion tool) Versions: Python 3.2, Python 3.3
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Aaron.Meurer, VPeric, benjamin.peterson, petri.lehtinen, pitrou, smarnach
Priority: normal Keywords:

Created on 2011-11-03 12:11 by smarnach, last changed 2011-11-04 00:11 by Aaron.Meurer.

Messages (6)
msg146918 - (view) Author: Sven Marnach (smarnach) Date: 2011-11-03 12:11
The execfile fixer of the 2to3 script replaces the 2.x code

    execfile("a.py")

by

    exec(compile(open("a.py").read(), "a.py", 'exec'))

The new code does not explicitly close the file.  This is not usually a problem in CPython, but

 1. the code will throw a RessourceWarnings if enabled and

 2. other Python implementation don't close the file immediately.

(I think the 2to3 script should be as implementation-independent as possible.)

The obvious fix would be to use a with-statement:

    with open("a.py") as new_name:
        exec(compile(new_name.read(), "a.py", 'exec'))

If this is to be changed, I'd be happy to prepare a patch.
msg146924 - (view) Author: Petri Lehtinen (petri.lehtinen) * (Python committer) Date: 2011-11-03 12:25
Sounds reasonable to me. Is it easy to generate unique identifier names in 2to3 fixers?
msg146925 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-11-03 12:29
Be aware that execfile() is a simple function call and can be used in any expression.
msg146931 - (view) Author: Sven Marnach (smarnach) Date: 2011-11-03 13:11
@Petri: Yes, that's what the BaseFix.new_name() method is for.

@Antoine: I thought about this, though I don't think it is very common to call execfile() as part of an expression. The whole statement containing the function call would need to be wrapped.
msg146953 - (view) Author: Sven Marnach (smarnach) Date: 2011-11-03 17:34
Getting the general case right seems a bit too difficult.  Examples like

    [execfile(n) for n in names if condition(n)]

    execfile(execfile(n1) or n2)

    try: 1 / 0
    except execfile(n) or ZeroDivisionError: pass

would require rather complex transformations to get exactly matching behaviour, and obviously we don't want to explode the fixer code to support such nonsense.

I think it is enough to cover the case of an execfile() call that forms a statement of its own.  Browsing through the first ten pages of a Google code search for "execfile" didn't reveal any other uses, except for a few that aren't covered by the current version of the fixer either. [1]

I'd suggest to simply throw a "could not convert" warning for any other uses of execfile().  Opinions?

[1]: http://www.google.com/codesearch#yqvQ9RM69FY/mercurial/lsprof.py&q=execfile&sq=&l=111&ct=rc&cd=49
msg146977 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2011-11-03 20:30
Or you could just explicitly write out the exec(compile()) in your 2.x code.
History
Date User Action Args
2011-11-04 00:11:06Aaron.Meurersetnosy: + Aaron.Meurer
2011-11-03 21:58:51VPericsetnosy: + VPeric
2011-11-03 20:30:55benjamin.petersonsetmessages: + msg146977
2011-11-03 17:34:47smarnachsetmessages: + msg146953
2011-11-03 13:11:18smarnachsetmessages: + msg146931
2011-11-03 12:29:19pitrousetnosy: + pitrou, benjamin.peterson
messages: + msg146925
2011-11-03 12:25:19petri.lehtinensetnosy: + petri.lehtinen
messages: + msg146924
2011-11-03 12:11:31smarnachcreate