Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When designing a Python API, is it more Pythonic to throw exceptions or return false/None, etc?

I am using a Python based API where there are lots of functions to query things, like doesPointExist, findPoint, canCreateNewPoint, etc where the negative result throws an exception. This makes the code much more cluttered filled with try/catch statements, instead of directly using the result as a boolean value.

Since I am not a Python expert, I am wondering if this design is Pythonic or not? I haven't seen this sort of design in the standard libraries though, so I am assuming this kind of exception usage in Python APIs is frowned upon?

like image 640
Joan Venge Avatar asked Nov 20 '13 13:11

Joan Venge


4 Answers

API design is a bit of an art. The name of a function should suggest how it will behave, including setting up user expectations. A function named findPoint implies that the search may fail, so the case where no such point exists is not exceptional, and may return None to signal the result. A function named getPoint, however, would imply to me that it can always return the requested point. A failure would be unexpected and warrant raising an exception.

like image 163
chepner Avatar answered Nov 20 '22 04:11

chepner


Sounds like a badly designed API.

  • The function doesPointExist should return True or False, it shouldn't raise an exception when the point doesn't exist.
  • The function findPoint should return a Point object or None when no object could be found.
  • The function canCreateNewPoint should return True or False for similar reasons.

Exceptions are for exceptional cases.

like image 26
Simeon Visser Avatar answered Nov 20 '22 04:11

Simeon Visser


I don't agree that you won't find this in the standard library. For example, "abc".index("d") raises ValueError, lots of libraries raise exceptions freely.

I'd say it depends on what the consequences of a failed action are.

  • If the caller can work with the returned value without change, I'd return an empty value (or False, if it's a yes or no question).
  • If the call fails, I'd raise an exception. For example findPoint() might do that if it normally returns a Point object that the caller wants to work with.
like image 3
Tim Pietzcker Avatar answered Nov 20 '22 04:11

Tim Pietzcker


1, I would recommend to use exception for very specific cases, so you do not need to test for them in common situations.

2, You should read guidelines PEP8 Naming Conventions regarding the names of your functions.

like image 2
Jiri Avatar answered Nov 20 '22 05:11

Jiri