[Python-Dev] cpython: Rename contextlib.ignored() to contextlib.ignore(). (original) (raw)

Nick Coghlan ncoghlan at gmail.com
Tue Oct 15 02🔞56 CEST 2013


On 14 Oct 2013 09:28, "Glenn Linderman" <v+python at g.nevcal.com> wrote:

On 10/12/2013 11:57 PM, Nick Coghlan wrote:

For the record, this thread did prompt me to consider the new construct anew, but on reflection, I still consider it a reasonable addition to contextlib. It substantially improves the simple cases it is intended to help with, and, if anything, makes overly broad exception suppression more obviously dubious (because the name of the construct doesn't match the consequences for multi-line suites). For the record, the logic in the last paragraph is the most dubious thing I've ever seen you post.

I didn't articulate the point very well. The reason I originally approved the change (and the reason I have kept it despite the objections raised) is because it allows correct-but-ugly code like:

try:
    os.unlink(fname)
except FileNotFoundError:
    pass

To be rewritten as the significantly more elegant:

with ignore(FileNotFoundError):
    os.unlink(fname)

which is much closer to the version that expects to have complete control over the file's lifecycle:

os.unlink(fname)

The more explicit statement of intent can also be exploited in static code analysis (such as linting), although I don't expect anyone to actually do that any time soon.

This benefit when used correctly then needs to be weighed against the risk of it being used incorrectly, especially by people that expect it to work like VB's "on error resume next" rather than by suppressing the exception and resuming execution after the with statement.

The problem of overbroad exception handling isn't a new one, though, and I don't believe this feature makes that problem worse, and, by making it simpler and cleaner to suppress exceptions from a single statement, may make it better. For example, this code is wrong:

try:
    os.unlink(fname)
    os.unlink(fname2)
except FileNotFoundError:
    pass

You could fix this particular case with a loop (since the two commands differ by a single value), but that option isn't always going to be available. Requiring 3 extra lines per command is a significant factor pushing against correctly suppressing exceptions from cleanup code that may fail for legitimate reasons. The new CM handles these cases a little more neatly, in a way that doesn't require the use of a loop:

with ignore(FileNotFoundError):
    os.unlink(fname)
with ignore(FileNotFoundError):
    os.unlink(fname2)

What the new CM doesn't handle nicely is multi-statement suites, and I'm OK with that. Handling those is not what this CM is for, and I believe trying to generalise it would harm the primary intended use case.

I now do plan to experiment with a more general with statement termination construct in contextlib2 before Python 3.5, but that's orthogonal to this change.

Regards, Nick.


Python-Dev mailing list Python-Dev at python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.python.org/pipermail/python-dev/attachments/20131015/017500ed/attachment.html>



More information about the Python-Dev mailing list