[Tutor] Examples of "With....As Statement" in Python
Steven D'Aprano
steve at pearwood.info
Tue Jul 10 18:05:32 CEST 2012
James Bell wrote:
> I'm attempting to learn how to use the "with....as" statement in python.
>
> I've read the documentation and also a few tutorials but I still cannot
> understand the concept. or how this is normally used. Can someone please
> write an example or 2 of simple ways to use the "with statement".
>
> I understand in java the try...catch...finally block so maybe someone can
> point out the relationship between them.
Java's try...catch...finally is called try...except...finally in Python.
In simple terms, a with-block uses a "context manager" to automatically wrap
code in a try...finally block so as to ensure that cleanup code runs
automatically even in the event of an error.
So that's the basic principle. Instead of having to write this *every time*
you need to process some stuff:
initialisation code
try:
process stuff
finally:
clean up code
you can write the initialisation and cleanup code *once* in a context manager,
then do:
with context manager:
process stuff
and have both the initialisation and cleanup code automatically handled by the
context manager.
So what's a context manager? I'll tell you what they *aren't* -- they are NOT
a special type or class. Any class can be a context manager if it obeys the
right protocol:
* the class must have a special method called __enter__
* the class must have a special method called __exit__
Of course, both __enter__ and __exit__ have to get the details right: they
have to take the right number of arguments, and do the right thing.
Other than than, any class or type can be context managers, and Python comes
with a few built in. The most important are file objects: any file object is
also a context manager, so you can say:
with open("myfile.txt") as f:
process(f)
and the file object will be automatically closed when the with block is done,
even if an error occurs.
Some other examples (from memory) include decimal Context objects, unittest
test features, and probably quite a few others.
How do you use a context manager? Easy -- you just call it using "with".
py> with open("rubbish.txt", "w") as fp:
... fp.write("starting to write...")
... fp.write(99) # oops!
...
20
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
TypeError: must be str, not int
py>
py> open("rubbish.txt").read()
'starting to write...'
Opening the file a second time (this time *without* the with statement) shows
that despite the error, the text was saved to disk and the file closed without
any additional effort.
So how do you write your own context manager?
Naturally you can just define a class and give it the appropriate __enter__
and __exit__ methods. But there's an easy way. Python has a library to help
you write context manager objects. Here's a toy example:
import contextlib
@contextlib.contextmanager
def my_manager(obj):
print("called manager with argument %s" % obj)
print("setting up manager...")
try:
value = ['anything', 'you', 'like', str(obj)]
yield value
finally:
print("cleanup code running...")
Now I can use my_manager in a with-statement:
py> with my_manager(42) as data:
... print("processing data")
... data.sort()
... print(data)
...
called manager with argument 42
setting up manager...
processing data
['42', 'anything', 'like', 'you']
cleanup code running...
--
Steven
More information about the Tutor
mailing list