On 5/18/2019 8:13 PM, Yonatan Zunger wrote:
Hi everyone,

I'd like to bounce this proposal off everyone and see if it's worth formulating as a PEP. I haven't found any prior discussion of it, but as we all know, searches can easily miss things, so if this is old hat please LMK.

*Summary: *The construction

with expr1 as var1, expr2 as var2, ...:
     body

fails (with an AttributeError) unless each expression returns a value satisfying the context manager protocol. Instead, we should permit any expression to be used. If a value does not expose an __enter__ method, it should behave as though its __enter__ method is return self; if it does not have an __exit__ method, it should behave as though that method is return False.

So far, -1. I think trying to use a non-context manager, in particular None, as a context manager, *should* raise. Since 'with' was introduced, we have gradually added the CM methods to most everything that *should* be a CM. If you think something else specific needs conversion, please open a new thread.


*Rationale: *The with statement has proven to be a valued extension to Python. In addition to providing improved readability for block scoping, it has strongly encouraged the use of scoped cleanups for objects which require them, such as files and mutices, in the process eliminating a lot of annoying bugs. I would argue that at present, whenever dealing with an object which requires such cleanup at a known time, with should be the default way of doing it, and /not/ doing so is the sort of thing one should be explaining in a code comment. However, the current syntax makes a few common patterns harder to implement than they should be.

For example, this is a good pattern:

with functionReturningFile(...) as input:
    doSomething(input)

There are many cases where an Optional[file] makes sense as a parameter, as well; for example, an optional debug output stream, or an input source which may either be a file (if provided) or some non-file source (by default). Likewise, there are many cases where a function may naturally return an Optional[file], e.g. "open the file if the user has provided the filename." However, the following is /not/ valid Python:

with functionReturningOptionalFile(...) as input:
    doSomething(input)

To handle this case, one has a few options. One may only use the 'with' in the known safe cases:

inputFile = functionReturningOptionalFile(...)
if inputFile:

Or more expicitly, 'if inputFile is not None:'

     with inputFile as input:
         doSomething(input)
else:
     doSomething(None)


When a function returns something useful or None, I think an immediate test is generally good practice. It will usually make the code clearer to readers.

--
Terry Jan Reedy


_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to