Why does from scipy import spatial work, while scipy.spatial doesn't work after import scipy?
Asked Answered
M

4

29

I would like to use scipy.spatial.distance.cosine in my code. I can import the spatial submodule if I do something like import scipy.spatial or from scipy import spatial, but if I simply import scipy calling scipy.spatial.distance.cosine(...) results in the following error: AttributeError: 'module' object has no attribute 'spatial'.

What is wrong with the second approach?

Marylouisemaryly answered 12/1, 2014 at 5:40 Comment(2)
@alKid and @falsetru gave good answers, and you should accept one of them. To explain why this is the case for scipy in particular, the reason that we do not import all subpackages is that there are a lot of them and many have large extension modules that consume quite a bit of time to load. Most programs don't need all of scipy loaded, so that would add a lot of extra overhead to all programs if we always imported all subpackages.Mutiny
This answer given by "alKid" and "falsetru" are not factually correct and rather misleading. The reason lies in the init files of the package. The init of scipy does not import its modules while the init of some other packages like numpy imports its modules. See better answers at the duplicate thread: #33380076Bettinabettine
R
32

Importing a package does not import submodule automatically. You need to import submodule explicitly.

For example, import xml does not import the submodule xml.dom

>>> import xml
>>> xml.dom
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'dom'
>>> import xml.dom
>>> xml.dom
<module 'xml.dom' from 'C:\Python27\lib\xml\dom\__init__.pyc'>

There's an exception like os.path. (os module itself import the submodule into its namespace)

>>> import os
>>> os.path
<module 'ntpath' from 'C:\Python27\lib\ntpath.pyc'>
Radiosurgery answered 12/1, 2014 at 5:48 Comment(0)
P
14

That's because scipy is a package, not a module. When you import a package, you don't actually load the modules inside, and thus package.module causes an error.

However, import package.module would work, because it loads the module, not the package.

This is the standard behavior for most import statements, but there are a few exceptions.

Here is the same case for urllib in Python 3:

>>> import urllib
>>> dir(urllib)
['__builtins__', '__cached__', '__doc__', '__file__', '__initializing__', '__loader__', '__name__', '__package__', '__path__', 'error', 'parse', 'request', 'response']

See? there is no submodules there. To access its submodule, we ask for the submodule:

>>> import urllib.request
>>> 

Hope this simple explanation helps!

Prospector answered 12/1, 2014 at 5:47 Comment(0)
S
2

Use following line to import:

import scipy.spatial # worked.

instead of

import scipy # not working

I tried and it worked.

Sickert answered 25/6, 2022 at 14:22 Comment(0)
K
-1

Use scipy version 1.2.1 to solve this issue......

Kirschner answered 19/2, 2020 at 8:55 Comment(2)
Always elaborate your answer. In this case, you can say what betterment is available in 1.2.1 version or the bug fixed, etc.Gaskins
Welcome to SO. Unfortunately, your answer both doesn't answer the OP's question of "What is wrong with the second approach?" and it is incorrect. Even with scipy 1.4.1 the second approach still results in AttributeError: module 'scipy' has no attribute 'spatial'Supportable

© 2022 - 2024 — McMap. All rights reserved.