Nevermind that this feature isn't particularly exciting... Python 3.1 is "old." Python 3.2 has been out for a while, 3.3 will be coming out soon... there are plenty of interesting features in 3.x. This is a small part of the overall picture. Rock on, Py3k devs.
This is cool.. But of the things that 3.1 has got me excited about, this doesn't really move the needle. It's pretty straight forward to throw together a context manager that deals with multiple files and access using `files.in` and `files.out` if you want to.
It's not that straightforward to create your own context manager, and creating a correct generic wrapper for the use case of composing multiple context managers is even harder (as demonstrated by the woes of contextlib.nested).
And if you're going to create a custom "composed" context manager every single time, you're probably better off just nesting `with` statements.
You're missing that if an exception gets thrown, the files are still guaranteed to be closed as soon as you exit that 'with' block.
Imagine you open 'infile', but then opening 'outfile' fails. To prevent a resource leak, now you need to close 'infile'. The linked code guarantees this. Likewise if there is any error which aborts the copying, both files will get closed and you don't have to worry so much about corner cases.
In a more complex application, an exception might be thrown before the last line that closes the file (and caught god knows where or not at all), so the files may not be closed... then again, if you actually try to catch the exceptions you get an extra level of indentation by using `with`.
Glad it helped you, but I wouldn't say "a clearer syntax for exception handling" really... more like a "way to ensure your code always works without having to actually think about exceptions". (Wrong as it may seem, I try to imagine I'm using "let" in a Lisp and then I instantly start to love the "with" syntax, although it's not a necessary part of Python :) )
"MIND == BLOWN" is a hyperbole in almost every context, but the `with` statement is just cleaner code with fewer chances to screw up (e.g. by forgetting to close).
I think "with" is a great example of where Python and Ruby differ philosophically. Python uses "with" to very explicitly implement their state manager protocol.
Ruby doesn't need "with" because "with" is really just a limited special case of what you can do with blocks.
The Python fans will counter that their less general solution is harder to abuse.
> The Python fans will counter that their less general solution is harder to abuse.
Not sure why anybody would say that, you can plenty abuse `with` if you want to have fun, the only thing you can't do is "dual-use" the block really (grab a context and invoke the block multiple times). And that you could always do with a decorator, if you're going there. The only thing `with` is is less flexible/general.
`unwind-protect` or `BlockClosure#ensure:` are probably much better examples of the philosophy opposite python though, I've always found ruby rather half-assed.
Nothing got better with Python 3? What about the print function and true division? Sure, those are both there as from __future__ import's, but I'd definitely call those improvements.
I haven't switched to Py3k yet either, but I'm just waiting for a few more packages I use heavily to get the bugs worked out.
> What about the print function and true division?
Those are actually fairly minor in the grand scheme of things (and compound `with` statements have been backported to 2.7).
More interesting are:
3.0
* unicode strings by default and much better overall support of unicode
* chained exceptions (I don't believe they've been backported)
3.2
* argparse merged to the stdlib
* ElementTree 1.3 finalized in stdlib (3.2)
* functools.lru_cache, itertools.accumulate (nothing game-changing, but nice to have in the stdlib)
* threading.Barrier
* concrete tzinfo implementation (for fixed UTC offsets)
* contextlib.ContextDecorator (creates a type which works both as a contextmanager and a function decorator), and improved contextmanager support across the board (ftplib, popen, TarFile, ...)
3.3 (soon to be released)
* Virtual environments shipped by default
* Namespace packages
* Kind-of obscure, but flexible string representations (strings can dynamically and transparently switch their implementation between latin-1, ucs-2 and ucs-4, this kills the narrow/wide compile-flag shit and generally makes strings more space-efficient)
* sub-generator delegation, instead of:
for item in sub_generator_function():
yield item
you can just write:
yield from sub_generator_function().
it also correctly forwards sent and thrown values (generator.send() and generator.throw()) to the sub-generator, so it actually translates into an unholy mess which now just works and allows more easily splitting a large function into sub-iterators.
* lzma/xz support (7z)
I'm actually excited for 3.3, there's plenty of cool stuff in there.
Yes, basically the only difference is that Python's with operates over a context management protocol involving some `__magic__` methods so it can work with other things in addition to files.
You can also do that in common-lisp by using the special form `with-open-file` is built upon: unwind-protect[0]. `with-open-file` is just a macro over it, specialized for files handling.
Not being mean, but this article kinda made me laugh. Python 3.1 has been out over 3 years[1]. And with the over the top "Mind == BLOWN"... Somebody should have told him about that release 3 years ago :-)