DEV Community

Discussion on: Python exceptions considered an anti-pattern

Collapse
 
misobelica profile image
Mišo

I was thinking about exceptions recently too. But I don't consider them an anti-pattern only the support in IDEs and type systems is not very good. And somehow I see it also in your example with pipeline/safe decorators. Where is the difference? Because I see a lot in the comments that you have problem with the second exceptional flow but doesn't have your solution the same problem? And isn't it even worse because you don't a see a big stacktrace with the info about the exception? Let me describe what I see.

@pipeline
def pipeline(...):
    one().unwrap()
    two().unwrap()
    return three()

@pipeline
def parent_pipeline():
    pipeline().unwrap()
    ...

@pipeline
def grand_pipeline():
    parent_pipeline().unwrap()
    ...
Enter fullscreen mode Exit fullscreen mode

So when the function two returns error the flow jumps to grand_pipeline exactly the same. And without the decorator with the proper exceptions the situation is also the same but with extra boilerplate of checking the result and returning upwards ala Golang. Rust has nice syntax sugar like two()? but still.

If I rewrite the code to use exceptions I see the same but without extra @safe and .unwrap() boilerplate. So where is the difference? If you read my article you will see I agree with that exceptions are hard to notice but I believe they can be fixed. By typesystem. Or even maybe by IDEs. What do you think about that? Still consider them anti-pattern even if they were upgraded?

I am still researching how the exceptions work under the hood and how stack unwinding affects the flow to complete my article but the idea there should be clear.

Collapse
 
sobolevn profile image
Nikita Sobolev

Well, @pipeline actually had multiple problems. And it is now removed from dry-python.
It is actually imperative compared to declarative function composition. Why so? Because @pipeline is an partial implementation of do-notation, which is imperative by definition.

But. The difference is still visible.

  1. Now exceptions can be visible in the funtion's signatire (let's use the same example from your post, even knowing that @pipeline is removed):
@pipeline
def grand_pipeline() -> Result[ValueType, ExceptionType]:
    parent_pipeline().unwrap()
Enter fullscreen mode Exit fullscreen mode

Here it is! We know that something happens! And we can express it with types.

  1. We have a special feature to enable stacktraces for your Results in development. See returns.readthedocs.io/en/latest/p...