This is a discussion on Python’s forums about adding something akin to a throws
keyword in python.
My counter: let’s throw Java into a pit
@Maoo @onlinepersona
That’s unfair. Java did everyone a huge favour by giving a practical demonstration of why (mandatory) checked exceptions are awful.
Yeah, let’s not. This is not a good idea
I disagree, I’d instead like to move toward handling errors as logic, and keeping exceptions for actually exceptional cases. If you’re expecting an exception, that’s data.
So here’s my proposal:
- introduce monads like Maybe/Result that forces the dev to handle expected errors in logic
- make an easy way to return errors early without interrupting logic flow
- simplify checking for None values in chaining
For the first (not exactly a monad, may need a new type to wrap things):
def maybe_err(val: int) -> Result[int, ValueError]:
if val < 0:
return ValueError("cannot be negative")
return val
match (val := maybe_err(-1)):
case int():
case ValueError():
For the second:
val = maybe_error(-1)? # special handling to return instances of Error early
And the third:
val = x?.y?.z ?? DEFAULT
I like this much better than having try/except blocks throughout the code, and reserve those only for logging and whatnot at the top level. If you document exceptions, people will use them even more as data instead of exceptions.
So only raise if you want it to bubble all the way up, return errors if it’s just data for the caller. Libraries should almost never raise.
@sugar_in_your_tea If you’re expecting exceptions, make custom ones. That’s the best way to distinguish between those you expect and those you don’t. Using custom exceptions improves readability too.
My point is that I don’t like using exceptions for communicating regular errors, only unrecoverable faults. So adding features to document exceptions better just doesn’t feel like the right direction.
Maybe that’s un-Pythonic of me, idk. From the zen of Python:
Errors should never pass silently.
Unless explicitly silenced.
Using monads could let programmers silently pass errors.
I just really don’t like the exception model after years of using other languages (mostly Rust and Go), I much prefer to be forced to contend with errors as they happen instead of just bubbling them up by default.
@sugar_in_your_tea The idea of exceptions is that you can choose when to deal with them. So if you want to deal with them immediately,
nothing is stopping you.
If you think handling errors with every function call explicitly is easier, I guess you’re using very few functions. For the project I’m working on, your proposal would probably double the number of lines. Thanks, but no thanks.
I’m not too familiar with C# (last used it like a decade ago), but I think the rules here would be pretty simple:
- x? - if x is None or an Error, return from the function early, otherwise use the value and continue
- x?.y - same as above, but with an attribute of x
- x ?? y - instead of returning as in the first, use y as the default value
And maybe add an option to convert exceptions from a function to an Error value (maybe some_func?()
to convert to error values? IDK, I haven’t thought through that part as much).
Hopefully that’s simple enough to be useful.
If I were proposing this, I’d limit it to optional chaining since that’s far more annoying to me currently.
When I used to write Java and switched to Python, this was one of the things I missed. It was always quite clear which exceptions I had to catch (or not). Just today, I ran into the issue of trying to cover the exceptions a library could throw without using except:
or except Exception as e
, but finally gave up and gave in to it. The linter wasn’t happy, but fuck it.
It was always quite clear which exceptions I had to catch (or not)
Lol. You’re literally the only one that likes checked exceptions. And, it seems you think that it actually gives you information about what exceptions to catch. It does not. Most things just catch and rethrow as a RuntimException
I also like checked exceptions. I like having a compile time check that I thought through error scenarios.
Is it perfect? No, but it should be iterated upon, not discarded.
FYI, catching and rethrowing as an unchecked exception is a pretty bad anti-patern (and a foul code smell).
Hey, I like checked exceptions too! I honestly think it’s one of Javas’s best features but it’s hindered by the fact that try-catch is so verbose, libraries aren’t always sensible about what exceptions they throw, and methods aren’t exception-polymorphic for stuff like the Stream API. Which is to say, checked exceptions are a pain but that’s the fault of the rest of the language around them and not the checked exceptions per se.
@onlinepersona You just need pip install fuckit