exec and locals
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
>> 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
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.