I'm developing a module that should be able to interact with other modules such as numpy or PIL. To accept parameters and test if, for example, a parameter is an numpy.ndarray
, I'd need to import numpy first.
What I used to do on previous projects is
numpy_exists = True
try:
import numpy as np
except:
numpy_exists = False
Then, when accepting parameters that could be of type <type numpy.ndarray>
I checked it like that:
if numpy_exists and type(param) == np.ndarray:
# ...
Now, it works, but it feels very weak because (personally) I look at the statement and the only thing I see is the NameError
this code could raise. Of course, it doesn't raise the error, but code like that makes me feel awkward when looking at it.
Is this a good way to handle the problem? Is there a better one?
-
What I don't understand is why would be missing a package that your module needs. I mean, if your module needs numpy in order to interact with it, just add required packages in the project's setup.py file.José María– José María2018年03月10日 10:16:50 +00:00Commented Mar 10, 2018 at 10:16
-
The catch is that my module does not need numpy. It can interact with numpy, if it helps the user's convenience. For example, the user can pass a file stream (of an image, for example) or a numpy array that represents a cv2 image. Then if the user does not want to have cv2 and numpy involved, they don't have to.Yotam Salmon– Yotam Salmon2018年03月10日 10:27:38 +00:00Commented Mar 10, 2018 at 10:27
1 Answer 1
I think that this is generally fine. But from a design standpoint, I'd probably solve it by moving the type checking for parameters in my own function (or even into a decorator, which looks much nicer). Then you can provide two different functions, depending on whether numpy exists or not, and don't even incur any speed cost. E.g:
def typecheck_without_numpy(...):
...
def typecheck_with_numpy(...):
...
try:
import numpy
typecheck = typecheck_with_numpy
except ImportError:
typecheck = typecheck_without_numpy
def some_function(x):
typecheck(x)
Of course, you can rename typecheck
to something like type_check_and_cast
and then either make it convert x to something your function can handle, or raise a TypeError
. This way, your code isn't littered by type checks, and as I said, you could move the typecheck into a decorator, so your functions would look something like
@typecheck
def some_function(x):
...
-
Must admit this looks much cleaner like you did it. Thanks.Yotam Salmon– Yotam Salmon2018年03月10日 13:43:54 +00:00Commented Mar 10, 2018 at 13:43