These are interesting ideas. It looks like you intend the except clause of the for loop to *only* cover the iter() and next() calls that are implicit in the for loop. You're right that it's awkward to catch exceptions there. However, I worry that when people see this syntax, they will think that the except clause is for handling exceptions in the loop body. (That's certainly what I assumed when I read just your subject line. :-)
Python allows you to write code in tight and readable form. Consider the
following example.
with connect() as stream: # connect() or __enter__() can fail.
for data in stream: # __next__() can fail
write(data) # write() can fail
The problem is that different lines can raise an exception of the same
type (for example OSError). We want to catch and handle exceptions
raised when open a connection, when read a data and when write a data in
different ways. Currently you need to expand so convenient Python
statements "with" and "for" (see PEP 343)
_mgr = connect()
_enter = type(_mgr).__enter__
_exit = type(_mgr).__exit__
_value = _enter(_mgr)
_exc = True
try:
stream = _value
_it = iter(stream)
while True:
try:
data = next(_it)
except StopIteration:
break
write(data)
except:
_exc = False
if not _exit(_mgr, *sys.exc_info()):
raise
finally:
if _exc:
_exit(_mgr, None, None, None)
and then add "try ... except" around corresponding explicit calls of
`__enter__()` and `next()`.
try:
_mgr = connect()
_enter = type(_mgr).__enter__
_exit = type(_mgr).__exit__
_value = _enter(_mgr)
_exc = True
except OSError:
handle_connection_error()
else:
try:
stream = _value
try:
_it = iter(stream)
except OSError:
handle_read_error()
else:
while True:
try:
data = next(_it)
except StopIteration:
break
except OSError:
handle_read_error()
break
try:
write(data)
except OSError:
handle_write_error()
except:
_exc = False
if not _exit(_mgr, *sys.exc_info()):
raise
finally:
if _exc:
_exit(_mgr, None, None, None)
Does not it look ugly?
I propose to add "except" clause to "for" and "with" statement to catch
exceptions in the code that can't be wrapped with "try ... except".
for VAR in EXPR:
BLOCK
except EXC:
HANDLER
should be equivalent to
try:
_it = iter(EXPR)
except EXC:
HANDLER
else:
while True:
try:
VAR = next(_it)
except StopIteration:
break
except EXC:
HANDLER
break
BLOCK
and
with EXPR as VAR:
BLOCK
except EXC:
HANDLER
try:
_mgr = EXPR
_enter = type(_mgr).__enter__
_exit = type(_mgr).__exit__
_value = _enter(_mgr)
_exc = True
except EXC:
HANDLER
else:
try:
VAR = _value
BLOCK
except:
_exc = False
if not _exit(_mgr, *sys.exc_info()):
raise
finally:
if _exc:
_exit(_mgr, None, None, None)
And correspondingly for asynchronous versions "async for" and "async with".
So you will be able to add errors handling like in:
with connect() as stream:
for data in stream:
try:
write(data)
except OSError:
handle_write_error()
except OSError:
handle_read_error()
except OSError:
handle_connection_error()
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/M76F3434TXNO2EUMZZ647EABTCNXYGXA/
Code of Conduct: http://python.org/psf/codeofconduct/
--