5 ms·
Agree. I spent quite a lot of effort at a previous role trying to convince junior developers to stop using except pretty much everywhere and just let the progra
by mindwok 3y ago
Agree. I spent quite a lot of effort at a previous role trying to convince junior developers to stop using except pretty much everywhere and just let the program explode, because that's really what you want most of the time. The problem is that sometimes in Python exceptions can be used for control flow, or for things that are reasonably common. In that case, it's very useful to know ahead of time what errors might be returned.
- dotancohen 3y ago> The problem is that sometimes in Python exceptions can be used for control flow, or for things that are reasonably common. Almost every time I've heard this argument, I've disagreed with it. I think that the only time using Exceptions for flow control was valid was some string-validation technique (like ensuring that a string was JSON or an email address) that could only throw an exception on error. I'd love to see _your_ use case, though.
- stevesimmons 3y ago> The problem is that sometimes in Python exceptions can be used for control flow, or for things that are reasonably common. Using exceptions for control flow is, imo, fine within a single function (e.g. for x in y: try: blah except KeyError: continue). Using exceptions for control flow across function boundaries seems a recipe for confusion, unless very clearly documented.
- tcfhgj 3y agoThe async library e.g. uses exceptions for queues.
- skitter 3y agoI'm confused — how would one use exceptions if not for control flow?
- tialaramex 3y agoIn general exceptions are error handling, for "exceptional" situations. For example suppose we're supposed to ensure the water flow is at least X litres per second, but now X is NaN, that's nonsense, raise an exception. You are correct that unlike a Result sum type, or an error code, or numerous other error solutions the exceptions inherently also change control flow. In Python though it's usual to (ab)use exceptions for other flows, for example to indicate that we're done, lets just throw a Done exception. The distinction is why Rust reifies control flow as the ControlFlow type, https://doc.rust-lang.org/core/ops/enum.ControlFlow.html https://doc.rust-lang.org/core/ops/enum.ControlFlow.html -- so we have shared vocabulary to distinguish "This failed w/ error X" Result::Err(X) from "We should stop now, result Y" ControlFlow::Break(Y) even though sometimes it's true that we're stopping because of an error so we end up transforming Result::Err(X) into ControlFlow::Break(X). Doing that transformation is what the Try trait, the operator ? does today it calls Try::branch(result) and if that's ControlFlow::Break(X) your function exits with X, if it's ControlFlow::Continue(C) then the operator's result is C.
- Skeime 3y agoI think any type of parsing benefits from some happy-path/unhappy-path support in the language, because parsing essentially is about figuring out whether your input conforms to some format and then translating it into a more useful representation. And it often works in a nested way, where you parse sub-parts of your input and then combine those parts later. If you don’t use some form of exceptions/result types/CPS, you end up with lots of code like if first part of input_data has format a: extract first part of output from input_data You need the checks because otherwise your program will blow up in the extract step, which in parsing is often not what you want, as you might need to try a different way of parsing the same thing first. Internally, the check and the extraction often do pretty similar things, so you’re duplicating your work. Here, exceptions for control flow can help, because instead of the check, you just try to extract, and if it doesn’t work, you try the next version. (However, result types usually work better for this, in programming languages that support them.) And as the last point, in my experience, many programming problems are handled cleanest when treating them as the problem of parsing some form of input (not necessarily a string) into some form of output. So this comes up more often than one might first think. [Also, Python uses exceptions for some types of control flow internally. For example, StopIteration is thrown by Iterators for the (rather unexceptional) case that the Iterator is finished producing output. Admittedly, you can almost always just use a for loop, except when you want access to the StopIteration’s value at the end.]
- fbdab103 3y agoChecking if a string represents an integer. There is a great SO post[0] with various alternatives, which all feel worse. [0] https://stackoverflow.com/questions/1265665/how-can-i-check-if-a-string-represents-an-int-without-using-try-except https://stackoverflow.com/questions/1265665/how-can-i-check-...
- Scarblac 3y agoThe way that an iterator signals that it is done iterating is by raising StopIteration ( https://docs.python.org/3/library/exceptions.html#StopIteration https://docs.python.org/3/library/exceptions.html#StopIterat... ). I don't know if it's still the case in Python 3, but in 2 that exception was core to how for loops and list comprehensions worked.
- ok123456 3y agoThis is still the case.