Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 'with' statement - how to tell what module/object/class supports it?

Tags:

python

Raymond Hettinger surprised quite a few people when he showed slides 36 and 37. https://speakerdeck.com/pyconslides/transforming-code-into-beautiful-idiomatic-python-by-raymond-hettinger -- Many people knew that the with statement could be used for opening files, but not these new things. Looking at python 3.3 docs on threading, only at the very bottom, section 16.2.8, is it even mentioned. From the lecture it was implied that using the 'with' operator was best practice.

  • How is one supposed to figure out if 'with' is supported, what it can be tied to, etc?
  • Also, how should 'with' be referred to? (threading with statement, python threading lock with statement,...), what is the vernacular to search and see if 'with' is supported (we can ask if something is iterable, do we ask if it's 'withable')?

ref:

  • http://docs.python.org/2/reference/compound_stmts.html#with 7.5
  • http://docs.python.org/2/reference/datamodel.html#context-managers 3.4.10
  • http://docs.python.org/3.1/library/threading.html 16.2.8
like image 447
pyInTheSky Avatar asked Apr 04 '13 19:04

pyInTheSky


People also ask

What is __ class __ in Python?

__class__ is an attribute on the object that refers to the class from which the object was created. a. __class__ # Output: <class 'int'> b. __class__ # Output: <class 'float'> After simple data types, let's now understand the type function and __class__ attribute with the help of a user-defined class, Human .

What is __ module __ in Python?

A module in Python is a file (ending in .py ) that contains a set of definitions (variables and functions) that you can use when they are imported. Modules are considered as objects, just as everything else is in Python. Many methods can operate on modules.

What is the with statement in Python?

The with statement in Python is used for resource management and exception handling. You'd most likely find it when working with file streams. For example, the statement ensures that the file stream process doesn't block other processes if an exception is raised, but terminates properly.

What is the context manager statement in Python?

Python provides an easy way to manage resources: Context Managers. The with keyword is used. When it gets evaluated it should result in an object that performs context management. Context managers can be written using classes or functions(with decorators).


2 Answers

First, you don't ask if something is "withable", you ask if it's a "context manager".*

For example, in the docs you linked (which are from 3.1, not 3.3, by the way):

Currently, Lock, RLock, Condition, Semaphore, and BoundedSemaphore objects may be used as with statement context managers.

Meanwhile, if you want to search in the interactive interpreter, there are two obvious things to do:

if hasattr(x, '__exit__'):
    print('x is a context manager')

try:
    with x:
        pass
except AttributeError:
    pass
else:
    print('x is a context manager')

Meanwhile:

help(open) … makes no mention of it

Well, yeah, because open isn't a context manager, it's a function that happens to return something that is a context manager. In 3.3, it can return a variety of different things depending on its parameters; in 2.7, it only returns one thing (a file), but help tells you exactly what it returns, and you can then use help on whichever one is appropriate for your use case, or just look at its attributes, to see that it defines __exit__.

At any rate, realistically, just remember that EAFTP applies to debugging and prototyping as well as to your final code. Try writing something with a with statement first. If the expression you're trying to use as a context manager isn't one, you'll get an exception as soon as you try to run that code, which is pretty easy to debug. (It will generally be an AttributeError about the lack of __exit__, but even if it isn't, the fact that the traceback says it's from your with line ought to tell you the problem.) And if you have an object that seems like it should be usable as a context manager, and isn't, you might want to consider filing a bug/bringing it up on the mailing lists/etc. (There are some classes in the stdlib that weren't context managers until someone complained.)

One last thing: If you're using a type that has a close method, but isn't a context manager, just use contextlib.closing around it:

with closing(legacy_file_like_object):

… or

with closing(legacy_file_like_object_producer()) as f:

In fact, you should really look at everything in contextlib. @contextmanager is very nifty, and nested is handy if you need to backport 2.7/3.x code to 2.5, and, while closing is trivial to write (if you have @contextmanager), using the stdlib function makes your intentions clear.


* Actually, there was a bit of a debate about the naming, and it recurs every so often on the mailing lists. But the docs and help('with') both give a nearly-precise definition, the "context manager" is the result of evaluating the "context expression". So, in with foo(bar) as baz, qux as quux:, foo(bar) and qux are both context managers. (Or maybe in some way the two of them make up a single context manager.)

like image 107
abarnert Avatar answered Nov 15 '22 00:11

abarnert


afaik any class/object that that implements __exit__ method (you may also need to implement __enter__)

>>>dir(file)
#notice it includes __enter__ and __exit__

so

def supportsWith(some_ob):
   if "__exit__" in dir(some_ob): #could justas easily used hasattr
       return True
like image 20
Joran Beasley Avatar answered Nov 14 '22 23:11

Joran Beasley