简体   繁体   中英

ModuleNotFoundError when packaging a Python project

I've developed a Python-based simulator and want to package it for the use of public.

Here is my setup.py :

import os

import setuptools
from setuptools import setup

from mypackage.version import __name__, __version__, __author__, __email__, __license__, __url__, \
    __description__, __keywords__, __classifiers__, __python_requires__
# ---------------------------------------------------------------------------------------------------------
# GENERAL
# ---------------------------------------------------------------------------------------------------------

thelibFolder = os.path.dirname(os.path.realpath(__file__))
requirementPath = thelibFolder + '/requirements.txt'
install_requires = []
if os.path.isfile(requirementPath):
    with open(requirementPath) as f:
        install_requires = f.read().splitlines()

data = dict(
    name=__name__,
    version=__version__,
    author=__author__,
    url=__url__,
    python_requires=__python_requires__,
    author_email=__email__,
    description=__description__,
    license=__license__,
    keywords=__keywords__,
    install_requires=install_requires,
    platforms='any',
    classifiers=__classifiers__
    # py_modules=['ipython']
)


# ---------------------------------------------------------------------------------------------------------
# OTHER METADATA
# ---------------------------------------------------------------------------------------------------------


# update the readme.rst to be part of setup
def readme():
    with open('README.md') as f:
        return f.read()


def packages():
    return ["mypackage"] + ["mypackage." + e for e in setuptools.find_packages(where='mypackage')]


data['long_description'] = readme()
data['long_description_content_type'] = 'text/x-rst'
data['packages'] = packages()
data['include_package_data'] = True


# ============================================================
# SETUP
# ============================================================


def run_setup(setup_args):
    # retrieve the original input arguments and execute default setup
    kwargs = setup_args
    setup(**kwargs)

    print('*' * 74)
    print("Python installation succeeded.")
    print('*' * 74)


run_setup(data)

And here is my requirements.txt :

ipython==7.29.0
ipython-genutils==0.2.0
attrs==21.2.0
cachetools==4.2.4
certifi==2021.10.8
chardet==4.0.0
cloudpickle==2.0.0
cycler==0.11.0
decorator==5.1.0
future==0.18.2
google-auth==2.3.3
gym==0.21.0
idna==3.3
iniconfig==1.1.1
kiwisolver==1.3.2
kubernetes==19.15.0
matplotlib==3.4.3
networkx==2.6.3
numpy==1.21.4
oauthlib==3.1.1
overloading==0.5.0
packaging==21.2
pandas==1.3.4
Pillow==8.4.0
pluggy==1.0.0
py==1.11.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
pyglet==1.5.21
pyparsing==3.0.6
pytest==6.2.5
python-dateutil==2.8.2
pytz==2021.3
PyYAML==6.0
requests==2.26.0
requests-oauthlib==1.3.0
rsa==4.7.2
scipy==1.7.2
seaborn==0.11.2
simpy==4.0.1
six==1.16.0
sortedcontainers==2.4.0
toml==0.10.2
typing==3.7.4.3
urllib3==1.26.7
websocket-client==1.2.1
prettytable==2.4.0

Then, I run the following to make the package: python3 setup.py sdist

It creates the package for me under dist , and then I can successfully upload it to a hosted repository (in my case gemfury.com). Of course, I can then pull it in a local project on my machine and can use my own package.

Then I try to create another python project, to basically use this package:

In requirements.txt :

--extra-index-url https://<my-token>@pypi.fury.io/<my-username>/
mypackage==0.1.0

In main.py :

from mypackage import MyServer

MyServer.run()

MyServer has a from IPython.display import Image, display in the beginning.

Then I make a Dockerfile to containerize this project:

FROM python:3.10
ADD main.py /
ADD requirements.txt /
RUN pip install -r requirements.txt
CMD [ "python", "./main.py"]

I then run the Dockerfile, it successfully pull mypackage, but then I get the following error:

 ... from IPython.display import Image, display ModuleNotFoundError: No module named 'IPython'

I still get the same error even if I manually add ipython to requirements.txt file in my dockerized project (in addition to having it requirements.txt in mypackage),

Any ideas?

Update 1: Here is the output of my docker build (when I just have mypackage in requirements):

> Preparing build context archive...
> [==================================================>]1153/1153 files
> Done
> 
> Sending build context to Docker daemon...
> [==================================================>] 3.788MB Done
> 
> Step 1/5 : FROM python:3.10  ---> 4246fb19839f 
> Step 2/5 : ADD main.py
> /  ---> Using cache  ---> 8dab230b6201 
> Step 3/5 : ADD requirements.txt
> /  ---> Using cache  ---> 2c56cb36982b 
> Step 4/5 : RUN pip install -r
> requirements.txt  ---> Running in e5ec7c02aaea Looking in indexes:
> https://pypi.org/simple, https://****@pypi.fury.io/michelgokan/
> Collecting mypackage==0.1.0   Downloading
> https://pypi.fury.io/michelgokan/-/ver_SqO4f/mypackage-0.1.0.tar.gz
> (62 kB)
>     ERROR: Command errored out with exit status 1:
>      command: /usr/local/bin/python -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] =
> '"'"'/tmp/pip-install-z_ofzy_s/mypackage_<some_number_here>/setup.py'"'"';
> __file__='"'"'/tmp/pip-install-z_ofzy_s/mypackage_<some_number_here>/setup.py'"'"';f
> = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import
> setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"',
> '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))'
> egg_info --egg-base /tmp/pip-pip-egg-info-fz0vejus
>          cwd: /tmp/pip-install-z_ofzy_s/mypackage_<some_number_here>/
>     Complete output (9 lines):
>     Traceback (most recent call last):
>       File "<string>", line 1, in <module>
>       File "/tmp/pip-install-z_ofzy_s/mypackage_<some_number_here>/setup.py",
> line 6, in <module>
>         from mypackage.version import __name__, __version__, __author__, __email__, __license__, __url__, \
>       File "/tmp/pip-install-z_ofzy_s/mypackage_<some_number_here>/mypackage/__init__.py",
> line 16, in <module>
>         from .helpers.utils import Utils
>       File "/tmp/pip-install-z_ofzy_s/mypackage_<some_number_here>/mypackage/helpers/utils.py",
> line 11, in <module>
>         from IPython.display import Image, display
>     ModuleNotFoundError: No module named 'IPython'
>     ---------------------------------------- WARNING: Discarding https://pypi.fury.io/username/-/<somthing>/mypackage-0.1.0.tar.gz#sha256=<some-token>
> (from https://pypi.fury.io/michelgokan/mypackage/)
> (requires-python:>=3.9). Command errored out with exit status 1:
> python setup.py egg_info Check the logs for full command output.
> ERROR: Could not find a version that satisfies the requirement
> mypackage==0.1.0 (from versions: 0.1.0)

and this is when I have copy paste the contents of mypackage `requirements.txt` to this new dockerized project's requirements.txt:

> Preparing build context archive...
> [==================================================>]1153/1153 files
> Done
> 
> Sending build context to Docker daemon...
> [==================================================>] 3.788MB Done
> 
> Step 1/5 : FROM python:3.10  ---> 4246fb19839f Step 2/5 : ADD main.py
> /  ---> Using cache  ---> 8dab230b6201 Step 3/5 : ADD requirements.txt
> /  ---> Using cache  ---> 050eebba6079 Step 4/5 : RUN pip install -r
> requirements.txt  ---> Running in edd3d9d868a1 Looking in indexes:
> https://pypi.org/simple, https://****@pypi.fury.io/michelgokan/
> Collecting IPython==7.29.0   Downloading
> ipython-7.29.0-py3-none-any.whl (790 kB) Collecting
> ipython-genutils==0.2.0   Downloading
> ipython_genutils-0.2.0-py2.py3-none-any.whl (26 kB) Collecting
> attrs==21.2.0   Downloading attrs-21.2.0-py2.py3-none-any.whl (53 kB)
> Collecting cachetools==4.2.4   Downloading
> cachetools-4.2.4-py3-none-any.whl (10 kB) Collecting
> certifi==2021.10.8   Downloading
> certifi-2021.10.8-py2.py3-none-any.whl (149 kB) Collecting
> chardet==4.0.0   Downloading chardet-4.0.0-py2.py3-none-any.whl (178
> kB) Collecting cloudpickle==2.0.0   Downloading
> cloudpickle-2.0.0-py3-none-any.whl (25 kB) Collecting cycler==0.11.0  
> Downloading cycler-0.11.0-py3-none-any.whl (6.4 kB) Collecting
> decorator==5.1.0   Downloading decorator-5.1.0-py3-none-any.whl (9.1
> kB) Collecting future==0.18.2   Downloading future-0.18.2.tar.gz (829
> kB) Collecting google-auth==2.3.3   Downloading
> google_auth-2.3.3-py2.py3-none-any.whl (155 kB) Collecting gym==0.21.0
> Downloading gym-0.21.0.tar.gz (1.5 MB) Collecting idna==3.3  
> Downloading idna-3.3-py3-none-any.whl (61 kB) Collecting
> iniconfig==1.1.1   Downloading iniconfig-1.1.1-py2.py3-none-any.whl
> (5.0 kB) Collecting kiwisolver==1.3.2   Downloading
> kiwisolver-1.3.2-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl
> (1.6 MB) Collecting kubernetes==19.15.0   Downloading
> kubernetes-19.15.0-py2.py3-none-any.whl (1.7 MB) Collecting
> matplotlib==3.4.3   Downloading matplotlib-3.4.3.tar.gz (37.9 MB)
> Collecting networkx==2.6.3   Downloading
> networkx-2.6.3-py3-none-any.whl (1.9 MB) Collecting numpy==1.21.4  
> Using cached
> numpy-1.21.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
> (15.9 MB) Collecting oauthlib==3.1.1   Downloading
> oauthlib-3.1.1-py2.py3-none-any.whl (146 kB) Collecting
> overloading==0.5.0   Downloading overloading-0.5.0-py3-none-any.whl
> (10 kB) Collecting packaging==21.2   Downloading
> packaging-21.2-py3-none-any.whl (40 kB) Collecting pandas==1.3.4  
> Downloading
> pandas-1.3.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
> (11.5 MB) Collecting Pillow==8.4.0   Downloading
> Pillow-8.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
> (3.1 MB) Collecting pluggy==1.0.0   Downloading
> pluggy-1.0.0-py2.py3-none-any.whl (13 kB) Collecting py==1.11.0  
> Downloading py-1.11.0-py2.py3-none-any.whl (98 kB) Collecting
> pyasn1==0.4.8   Downloading pyasn1-0.4.8-py2.py3-none-any.whl (77 kB)
> Collecting pyasn1-modules==0.2.8   Downloading
> pyasn1_modules-0.2.8-py2.py3-none-any.whl (155 kB) Collecting
> pyglet==1.5.21   Downloading pyglet-1.5.21-py3-none-any.whl (1.1 MB)
> Collecting pyparsing==3.0.6   Downloading
> pyparsing-3.0.6-py3-none-any.whl (97 kB) Collecting pytest==6.2.5  
> Downloading pytest-6.2.5-py3-none-any.whl (280 kB) Collecting
> python-dateutil==2.8.2   Downloading
> python_dateutil-2.8.2-py2.py3-none-any.whl (247 kB) Collecting
> pytz==2021.3   Downloading pytz-2021.3-py2.py3-none-any.whl (503 kB)
> Collecting PyYAML==6.0   Downloading
> PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
> (682 kB) Collecting requests==2.26.0   Downloading
> requests-2.26.0-py2.py3-none-any.whl (62 kB) Collecting
> requests-oauthlib==1.3.0   Downloading
> requests_oauthlib-1.3.0-py2.py3-none-any.whl (23 kB) Collecting
> rsa==4.7.2   Downloading rsa-4.7.2-py3-none-any.whl (34 kB) Collecting
> scipy==1.7.2   Downloading
> scipy-1.7.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
> (39.9 MB) Collecting seaborn==0.11.2   Downloading
> seaborn-0.11.2-py3-none-any.whl (292 kB) Collecting simpy==4.0.1  
> Downloading simpy-4.0.1-py2.py3-none-any.whl (29 kB) Collecting
> six==1.16.0   Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
> Collecting sortedcontainers==2.4.0   Downloading
> sortedcontainers-2.4.0-py2.py3-none-any.whl (29 kB) Collecting
> toml==0.10.2   Downloading toml-0.10.2-py2.py3-none-any.whl (16 kB)
> Collecting typing==3.7.4.3   Downloading typing-3.7.4.3.tar.gz (78 kB)
> Collecting urllib3==1.26.7   Downloading
> urllib3-1.26.7-py2.py3-none-any.whl (138 kB) Collecting
> websocket-client==1.2.1   Downloading
> websocket_client-1.2.1-py2.py3-none-any.whl (52 kB) Collecting
> prettytable==2.4.0   Downloading prettytable-2.4.0-py3-none-any.whl
> (24 kB) Collecting mypackage==0.1.0   Downloading
> https://pypi.fury.io/michelgokan/-/ver_SqO4f/mypackage-0.1.0.tar.gz (62
> kB)
>     ERROR: Command errored out with exit status 1:
>      command: /usr/local/bin/python -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] =
> '"'"'/tmp/pip-install-0c2n4ub7/mypackage_<some_number>/setup.py'"'"';
> __file__='"'"'/tmp/pip-install-0c2n4ub7/mypackage_<some_number>/setup.py'"'"';f
> = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import
> setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"',
> '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))'
> egg_info --egg-base /tmp/pip-pip-egg-info-sogtdamf
>          cwd: /tmp/pip-install-0c2n4ub7/mypackage_<some_number>/
>     Complete output (9 lines):
>     Traceback (most recent call last):
>       File "<string>", line 1, in <module>
>       File "/tmp/pip-install-0c2n4ub7/mypackage_<some_number>/setup.py",
> line 6, in <module>
>         from mypackage.version import __name__, __version__, __author__, __email__, __license__, __url__, \
>       File "/tmp/pip-install-0c2n4ub7/mypackage_<some_number>/mypackage/__init__.py",
> line 16, in <module>
>         from .helpers.utils import Utils
>       File "/tmp/pip-install-0c2n4ub7/mypackage_<some_number>/mypackage/helpers/utils.py",
> line 11, in <module>
>         from IPython.display import Image, display
>     ModuleNotFoundError: No module named 'IPython'

Based on

Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-z_ofzy_s/mypackage_<some_number_here>/setup.py",
line 6, in <module>
        from mypackage.version import __name__, __version__, __author__, __email__, __license__, __url__, \
      File "/tmp/pip-install-z_ofzy_s/mypackage_<some_number_here>/mypackage/__init__.py",
line 16, in <module>
        from .helpers.utils import Utils
      File "/tmp/pip-install-z_ofzy_s/mypackage_<some_number_here>/mypackage/helpers/utils.py",
line 11, in <module>
        from IPython.display import Image, display
    ModuleNotFoundError: No module named 'IPython'

your problem is that since you import mypackage.version , mypackage gets imported, which executes __init__.py . __init__.py imports mypackage.helpers.utils , which in turn requires IPython .

In other words, your package's setup.py won't work without IPython installed beforehand, and this is not quite related to Docker – any system without IPython would fail to install your package from source.

You might want to consider using the new declarative setup metadata system instead of a setup.py that needs to import your package, or to build wheels that don't have a setup.py.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM