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

Nick Coghlan ncoghlan at gmail.com
Tue Oct 15 02:18: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