exec and locals

Steven D'Aprano steve at pearwood.info
Thu Feb 27 20:49:10 EST 2014


On Fri, 28 Feb 2014 00:29:35 +1300, Gregory Ewing wrote:

> Steven D'Aprano wrote:
>> On Thu, 27 Feb 2014 16:34:33 +1300, Gregory Ewing wrote:
>> 
>>>Why not just use this version all the time? It should work in both 2.x
>>>and 3.x.
>> 
>> Because that's yucky. It's an aesthetic thing: when supported, I want
>> the Python interpreter to manage the context manager.
> 
> More yucky than wrapping the Py3 version in an exec? To my way of
> thinking, that cancels out any elegance that might have been gained from
> using a with-statement.
> 
> Do you really need to use the context manager at all? Could you just
> write the try-statement that you would have written in Py2 if you didn't
> have a context manager?

I don't *have* to do it any particular way, but the way it works now, the 
version of the inner function (which does eventually get exposed to the 
caller) is simple with statement wrapping a function call. So for seven 
of the eight versions of Python supported (2.5 through 3.4) the function 
is the simplest it can be. Even if the code creating that function is a 
tiny bit more complex, since it is wrapped inside an exec. For the other 
two versions (2.4 and 2.5), I have to fall back on a more complex chunk 
of code. (And yes, it's deliberate that 2.5 gets counted in both groups.)

I'm not saying that I have objective reasons for preferring this way over 
the manual alternative, or at least not *strong* objective reasons. It's 
mostly subjective. I don't expect to convince you my way is better, and I 
doubt that you'll convince me your way is better. But if I were to try, 
I'd put it this way:

At a cost of six (by memory) extra lines of code, including one call to 
exec, I have an inner function which is *guaranteed* to use the exact 
same semantics and efficiency of a with-statement when possible, because 
it *is* a with-statement. Any differences between with-statement and my 
manual handling will only affect 2.4 and sometimes 2.5, rather than 
everything. The only differences that I know of are insignificant -- the 
byte-code will be different, there may be trivial performance differences 
-- but if it turns out to be some meaningful difference, I have three 
choices:

  1) deny that the difference is meaningful;

  2) accept that the difference is meaningful, and fix it; or

  3) accept that the difference is meaningful, but say that it 
     won't be fixed for 2.4 and 2.5.


If I use the same manual handling for all versions, then I don't have 
that last option, no matter how unlikely it is that I will need it.

But really, it's a subjective choice of what feels right to me in this 
instance. If the body of the with-statement was bigger, or if the feature 
in question was something else, I might choose a different approach.



-- 
Steven



More information about the Python-list mailing list