Search code examples
pythonpackagepypi

Python package works fine except when downloaded from PyPI (AttributeError)


I am developing a Python package for laser beam analysis. The source code (setup.py, tox.ini, travis.tml) can be found on the Git repo and the complete documentation can be found on the ReadTheDocs page. The package is uploaded to PyPI and the tests are run with Travis CI.

Here is a brief description of the package structure:

beamprofiler
|
|---__init__.py
|---beam.py
|
/---utils
|   |
|   |---__init__.py
|   |---data_processing.py
|   |---plot.py
|   |---report.py
|
/---iso
|   |
|   |---__init__.py
|   |---characterizing_parameters.py
|   |---measured_quantities.py
|
/---niso
|   |---__init__.py
|   |---characterizing_parameters.py

Currently all tests are passing in Travis CI, and I can install and run my package locally with python setup.py install without any issues (tests also pass locally).

Here is the catch: when I download the package from PyPI I get the following errors:

  • AttributeError: module 'beamprofiler.utils' has no attribute 'plot'
  • AttributeError: module 'beamprofiler.utils' has no attribute 'report'

Upon further investigation I found that all other sub-packages and modules are present, even the module beamprofiler.utils.data_processing, which is from the same utils sub-package. So it seems that this isn't an issue with the sub-package utils, but rather with the modules plot and report.

beamprofiler
Out[14]: <module 'beamprofiler' from 'C:\\Users\\wagnojunior.ab\\Anaconda3\\envs\\beam\\lib\\site-packages\\beamprofiler\\__init__.py'>

beamprofiler.beam
Out[15]: <module 'beamprofiler.beam' from 'C:\\Users\\wagnojunior.ab\\Anaconda3\\envs\\beam\\lib\\site-packages\\beamprofiler\\beam.py'>

beamprofiler.iso
Out[16]: <module 'beamprofiler.iso' from 'C:\\Users\\wagnojunior.ab\\Anaconda3\\envs\\beam\\lib\\site-packages\\beamprofiler\\iso\\__init__.py'>

beamprofiler.niso
Out[17]: <module 'beamprofiler.niso' from 'C:\\Users\\wagnojunior.ab\\Anaconda3\\envs\\beam\\lib\\site-packages\\beamprofiler\\niso\\__init__.py'>

beamprofiler.utils
Out[18]: <module 'beamprofiler.utils' from 'C:\\Users\\wagnojunior.ab\\Anaconda3\\envs\\beam\\lib\\site-packages\\beamprofiler\\utils\\__init__.py'>

beamprofiler.utils.data_processing
Out[19]: <module 'beamprofiler.utils.data_processing' from 'C:\\Users\\wagnojunior.ab\\Anaconda3\\envs\\beam\\lib\\site-packages\\beamprofiler\\utils\\data_processing.py'>

beamprofiler.utils.plot
Traceback (most recent call last):

  Input In [20] in <cell line: 1>
    beamprofiler.utils.plot

AttributeError: module 'beamprofiler.utils' has no attribute 'plot'


beamprofiler.utils.report
Traceback (most recent call last):

  Input In [21] in <cell line: 1>
    beamprofiler.utils.report

AttributeError: module 'beamprofiler.utils' has no attribute 'report'

I thought it might be a broken wheel file so I rebuilt the project and checked with twine check dist/* with no issues:

Checking dist\beamprofiler-1.0.0-1-py2.py3-none-any.whl: PASSED
Checking dist\beamprofiler-1.0.0-1.tar.gz: PASSED

After that I re-uploaded to PyPI but the problem still persists... I cannot get my head around it, so I appreciate your inputs.

Thanks!


Solution

  • This is not related to PyPI. Actually, I got the same behaviour when installing via python setup.py install or pip install .

    You need to add from . import data_processing, plot, report in your src/beamprofiler/utils/__init__.py file (I recommand to do it also in your other __init__ files).

    This is the way python works. If these imports are not in your init file, you can only import them with from beamprofiler.utils import plot, but you can't directly use beamprofiler.utils.plot.

    Note that all the other cases you mentionned worked because they where imported in your src/beamprofiler/beam.py file (all, except plot and report). Try to comment out from beamprofiler.beam import Beam in your main init file and you will see that it will create the same behaviour with your other modules:

    >>> import beamprofiler
    >>> beamprofiler.utils.data_processing
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: module 'beamprofiler.utils' has no attribute 'data_processing'