pytorch, AttributeError: module 'torch' has no attribute 'Tensor'

DavideChicco.it picture DavideChicco.it · Nov 15, 2017 · Viewed 28.5k times · Source

I'm working with Python 3.5.1 on a computer having CentOS Linux 7.3.1611 (Core) operating system.

I'm trying to use PyTorch and I'm getting started with this tutorial.

Unfortunately, the #4 line of the example creates troubles:

>>> torch.Tensor(5, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'torch' has no attribute 'Tensor'

I cannot understand this error... of course in Torch the 'torch' does have an attribute 'Tensor'. The same command works in Torch.

How can I solve this problem?

Answer

Martijn Pieters picture Martijn Pieters · Nov 23, 2017

The Python binary that you are running does not have torch installed. It does have a directory named torch on the module search path, and it is treated as a namespace package:

$ pwd
/some/path
$ python3 -c 'import torch; print(torch); print(torch.__path__)'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'torch'
$ mkdir torch
$ python3 -c 'import torch; print(torch); print(torch.__path__)'
<module 'torch' (namespace)>
_NamespacePath(['/some/path/torch'])

Any directory without a __init__.py file present in it, located on your module search path, will be treated as a namespace, provided no other Python modules or packages by that name are found anywhere else along the search path.

This means that if torch was installed for your Python binary, it doesn't matter if there is a local torch directory:

$ ls -ld torch/
drwxr-xr-x  2 mjpieters users  68 Nov 23 13:57 torch/
$ mkdir -p additional_path/torch/
$ touch additional_path/torch/__init__.py
$ PYTHONPATH="./additional_path" python3 -c 'import os.path as p, sys; print(*(t for t in (p.join(e, "torch") for e in sys.path) if p.exists(t)), sep="\n")'
torch
/some/path/additional_path/torch
$ PYTHONPATH="./additional_path" python3 -c 'import torch; print(torch); print(torch.__path__)'
<module 'torch' from '/some/path/additional_path/torch/__init__.py'>
['/some/path/additional_path/torch']

The above shows that sys.path lists the torch directory first, followed by additional_path/torch, but the latter is loaded as the torch module when you try to import it. That's because Python gives priority to top-level modules and packages before loading a namespace package.

You need to install torch correctly for your current Python binary, see the project homepage; when using pip you may want to use the Python binary with the -m switch instead:

python3.5 -m pip install http://download.pytorch.org/whl/cu80/torch-0.2.0.post3-cp35-cp35m-manylinux1_x86_64.whl 
python3.5 -m pip install torchvision

So replace the pip3 the homepage instructions use with python3.5 -m pip; python3.5 can also be the full path to your Python binary.

Do use the correct download.pytorch.org URL for the latest version.

You don't have to move the directory aside, but if you do want to and don't know where it is located, use print(torch.__path__) as I've shown above.

Again, note that if you do have an __init__.py file in a local torch directory, it becomes a regular package and it'll mask packages installed by pip into the normal site-packages location. If you have such a package, or a local torch.py single-file module, you need to rename those. The diagnostic information looks different in that case:

$ pwd
/some/path
$ python3 -c 'import torch; print(torch); print(torch.__path__)'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'torch'
$ mkdir torch
$ touch torch/__init__.py  # make it a package
$ python3 -c 'import torch; print(torch); print(torch.__path__)'
<module 'torch' from '/some/path/torch/__init__.py'>
['/some/path/torch']
$ rm -rf torch/
$ touch torch.py           # make it a module
$ python3 -c 'import torch; print(torch); print(torch.__file__)'
<module 'torch' from '/some/path/torch.py'>
/some/path/torch.py

Note the differences; a namespace package, above, uses <module 'name' (namespace)>, while a regular package uses ), while a plain module uses`.

Such packages and modules (not namespace packages) are found first and stop the search. If the found package or module is not the one you wanted, you need to move them aside or rename them.