We should publish some advice on creating content managers.

Context managers are a general purpose tool but have a primary
use case of creating and releasing resources.  This creates an
expectation that that is what the context managers are doing unless
they explicitly say otherwise.

For example in the following calls, the content managers are responsible
for acquiring and releasing a resource.  This is a good and clean design:

    with open(filename) as f: ...      # will release the file resource when 
done

    with lock:                                     # will acquire and release 
the lock.

However, in the case that someone wants to create a context manager that does
something other than acquiring and releasing resources, then they should
create a separate content manager so that the behavior will be named.

In other words, if the behavior is going to be the common and expected case,
it is okay to add __enter__ and __exit__ to existing classes (as was done
for locks and files).  However, if the behavior is going to do something else,
then the __enter__ and __exit__ methods need to be in a new class or
factory function.

For example, given the typical uses of context managers, I would expect the 
following code to automatically close the database connection:

     with sqlite3.connect(filename) as db:
          ...

Instead, the context manager implements a different behavior.  It would
have been better if that behavior had been given a name:

    db = sqlite3.connect(filename)
    with auto_commit_or_rollback(db):
          # do a transaction

Explicit beats implicit whenever the implicit behavior would deviate from 
expected norms.


Raymond
    
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to