简体   繁体   中英

How do I define a Python class that I can use with the with statement?

I understand that StringIO acts like a file object, duck-typing what you would get from open('somefile.txt') .

Now I want to use StringIO with the with statement:

with StringIO('some string') as fh: # fh as in "file handle"
    data = [stuff from stuff in fh.read()]

But Python complains that type StringIO does not have an __exit__ method. After subclassing StringIO :

class MyStringIO(StringIO):
    def __exit__(self):
        self.close()

I now get an exception about not having an __enter__ method. How do I define the __enter__ method? What does Python expect from a class that can be used with the with statement?

You need to write a context manager . If you don't want to write the whole protocol, there's a simplified way around it using the contextlib.contextmanager decorator.

Just to give an example where it would be overkill do use contextlib, which is more for use with generators:

Here is a nice and useful example of a context manager. I found it in David Beazley's blog:

http://dabeaz.blogspot.de/2010/02/context-manager-for-timing-benchmarks.html

and just modified it a little bit to use the best timer per platform, a trick that I use from the timeit module:

# benchmark.py
import timeit
class benchmark(object):
    from timeit import default_timer as timer
    def __init__(self, name):
        self.name = name
    def __enter__(self):
        self.start = self.timer()
    def __exit__(self, ty, val, tb):
        end = self.timer()
        print("%s : %0.3f seconds" % (self.name, end-self.start))
        return False

Now that gives you a context manager that you can use like this:

with benchmark('algorithm 1'):
    ... (some computation)
with benchmark('other approach'):
    ... (some other computation)

and you get your output printed. I liked this example and wanted to share it.

you define the __enter__ method just as you did with __exit__ . these are the two methods needed for an object to be used with the with statement, see this for more info.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM