pythonnumpyherokuplotlyplotly-dash

ModuleNotFoundError: No module named 'setuptools.extern.six' (site-packages)


I'm new-ish to Python and I have made a web app with Dash and Plotly, but when I try to push my project to Heroku i keep getting this build error:

(venv) PS D:\Dev\election-2024> git push heroku main
Counting objects: 12, done.
Delta compression using up to 12 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (12/12), 1.03 KiB | 1.03 MiB/s, done.
Total 12 (delta 8), reused 0 (delta 0)
remote: Updated 7 paths from 6d25bef
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-24 stack
remote: -----> Determining which buildpack to use for this app
remote: -----> Python app detected
remote: -----> No Python version was specified. Using the buildpack default: Python 3.12
remote:        To use a different version, see: https://devcenter.heroku.com/articles/python-runtimes
remote: -----> Installing Python 3.12.7
remote: -----> Installing pip 24.0, setuptools 70.3.0 and wheel 0.44.0
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote:        Collecting certifi==2024.8.30 (from -r requirements.txt (line 1))
remote:          Downloading certifi-2024.8.30-py3-none-any.whl.metadata (2.2 kB)
remote:        Collecting charset-normalizer==2.0.12 (from -r requirements.txt (line 2))
remote:          Downloading charset_normalizer-2.0.12-py3-none-any.whl.metadata (11 kB)
remote:        Collecting click==8.0.4 (from -r requirements.txt (line 3))
remote:          Downloading click-8.0.4-py3-none-any.whl.metadata (3.2 kB)
remote:        Collecting colorama==0.4.5 (from -r requirements.txt (line 4))
remote:          Downloading colorama-0.4.5-py2.py3-none-any.whl.metadata (15 kB)
remote:        Collecting contextvars==2.4 (from -r requirements.txt (line 5))
remote:          Downloading contextvars-2.4.tar.gz (9.6 kB)
remote:          Preparing metadata (setup.py): started
remote:          Preparing metadata (setup.py): finished with status 'done'
remote:        Collecting dash==2.15.0 (from -r requirements.txt (line 6))
remote:          Downloading dash-2.15.0-py3-none-any.whl.metadata (11 kB)
remote:        Collecting dash-core-components==2.0.0 (from -r requirements.txt (line 7))
remote:          Downloading dash_core_components-2.0.0-py3-none-any.whl.metadata (2.9 kB)
remote:        Collecting dash-html-components==2.0.0 (from -r requirements.txt (line 8))
remote:          Downloading dash_html_components-2.0.0-py3-none-any.whl.metadata (3.8 kB)
remote:        Collecting dash-table==5.0.0 (from -r requirements.txt (line 9))
remote:          Downloading dash_table-5.0.0-py3-none-any.whl.metadata (2.4 kB)
remote:        Collecting Flask==2.0.3 (from -r requirements.txt (line 10))
remote:          Downloading Flask-2.0.3-py3-none-any.whl.metadata (3.8 kB)
remote:        Collecting gunicorn==21.2.0 (from -r requirements.txt (line 11))
remote:          Downloading gunicorn-21.2.0-py3-none-any.whl.metadata (4.1 kB)
remote:        Collecting idna==3.10 (from -r requirements.txt (line 12))
remote:          Downloading idna-3.10-py3-none-any.whl.metadata (10 kB)
remote:        Collecting immutables==0.19 (from -r requirements.txt (line 13))
remote:          Downloading immutables-0.19.tar.gz (85 kB)
remote:          Installing build dependencies: started
remote:          Installing build dependencies: finished with status 'done'
remote:          Getting requirements to build wheel: started
remote:          Getting requirements to build wheel: finished with status 'done'
remote:          Preparing metadata (pyproject.toml): started
remote:          Preparing metadata (pyproject.toml): finished with status 'done'
remote:        Collecting importlib-metadata==4.8.3 (from -r requirements.txt (line 14))
remote:          Downloading importlib_metadata-4.8.3-py3-none-any.whl.metadata (4.0 kB)
remote:        Collecting itsdangerous==2.0.1 (from -r requirements.txt (line 15))
remote:          Downloading itsdangerous-2.0.1-py3-none-any.whl.metadata (2.9 kB)
remote:        Collecting Jinja2==3.0.3 (from -r requirements.txt (line 16))
remote:          Downloading Jinja2-3.0.3-py3-none-any.whl.metadata (3.5 kB)
remote:        Collecting MarkupSafe==2.0.1 (from -r requirements.txt (line 17))
remote:          Downloading MarkupSafe-2.0.1.tar.gz (18 kB)
remote:          Preparing metadata (setup.py): started
remote:          Preparing metadata (setup.py): finished with status 'done'
remote:        Collecting nest-asyncio==1.6.0 (from -r requirements.txt (line 18))
remote:          Downloading nest_asyncio-1.6.0-py3-none-any.whl.metadata (2.8 kB)
remote:        Collecting numpy==1.19.5 (from -r requirements.txt (line 19))
remote:          Downloading numpy-1.19.5.zip (7.3 MB)
remote:          Installing build dependencies: started
remote:          Installing build dependencies: finished with status 'done'
remote:          Getting requirements to build wheel: started
remote:          Getting requirements to build wheel: finished with status 'done'
remote:        ERROR: Exception:
remote:        Traceback (most recent call last):
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/cli/base_command.py", line 180, in exc_logging_wrapper
remote:            status = run_func(*args)
remote:                     ^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/cli/req_command.py", line 245, in wrapper
remote:            return func(self, options, args)
remote:                   ^^^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/commands/install.py", line 377, in run
remote:            requirement_set = resolver.resolve(
remote:                              ^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/resolver.py", line 95, in resolve
remote:            result = self._result = resolver.resolve(
remote:                                    ^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_vendor/resolvelib/resolvers.py", line 546, in resolve
remote:            state = resolution.resolve(requirements, max_rounds=max_rounds)
remote:                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_vendor/resolvelib/resolvers.py", line 397, in resolve
remote:            self._add_to_criteria(self.state.criteria, r, parent=None)
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_vendor/resolvelib/resolvers.py", line 173, in _add_to_criteria
remote:            if not criterion.candidates:
remote:                   ^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_vendor/resolvelib/structs.py", line 156, in __bool__
remote:            return bool(self._sequence)
remote:                   ^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py", line 155, in __bool__
remote:            return any(self)
remote:                   ^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py", line 143, in <genexpr>
remote:            return (c for c in iterator if id(c) not in self._incompatible_ids)
remote:                               ^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py", line 47, in _iter_built
remote:            candidate = func()
remote:                        ^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 182, in _make_candidate_from_link
remote:            base: Optional[BaseCandidate] = self._make_base_candidate_from_link(
remote:                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 228, in _make_base_candidate_from_link
remote:            self._link_candidate_cache[link] = LinkCandidate(
remote:                                               ^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 290, in __init__
remote:            super().__init__(
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 156, in __init__
remote:            self.dist = self._prepare()
remote:                        ^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 222, in _prepare
remote:            dist = self._prepare_distribution()
remote:                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 301, in _prepare_distribution
remote:            return preparer.prepare_linked_requirement(self._ireq, parallel_builds=True)
remote:                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/operations/prepare.py", line 525, in prepare_linked_requirement
remote:            return self._prepare_linked_requirement(req, parallel_builds)
remote:                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/operations/prepare.py", line 640, in _prepare_linked_requirement
remote:            dist = _get_prepared_distribution(
remote:                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/operations/prepare.py", line 71, in _get_prepared_distribution
remote:            abstract_dist.prepare_distribution_metadata(
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/distributions/sdist.py", line 54, in prepare_distribution_metadata
remote:            self._install_build_reqs(finder)
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/distributions/sdist.py", line 124, in _install_build_reqs
remote:            build_reqs = self._get_build_requires_wheel()
remote:                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/distributions/sdist.py", line 101, in _get_build_requires_wheel
remote:            return backend.get_requires_for_build_wheel()
remote:                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_internal/utils/misc.py", line 745, in get_requires_for_build_wheel
remote:            return super().get_requires_for_build_wheel(config_settings=cs)
remote:                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py", line 166, in get_requires_for_build_wheel
remote:            return self._call_hook('get_requires_for_build_wheel', {
remote:                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py", line 321, in _call_hook
remote:            raise BackendUnavailable(data.get('traceback', ''))
remote:        pip._vendor.pyproject_hooks._impl.BackendUnavailable: Traceback (most recent call last):
remote:          File "/app/.heroku/python/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 77, in _build_backend
remote:            obj = import_module(mod_path)
remote:                  ^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "/app/.heroku/python/lib/python3.12/importlib/__init__.py", line 90, in import_module
remote:            return _bootstrap._gcd_import(name[level:], package, level)
remote:                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
remote:          File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
remote:          File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
remote:          File "<frozen importlib._bootstrap>", line 1310, in _find_and_load_unlocked
remote:          File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
remote:          File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
remote:          File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
remote:          File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
remote:          File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
remote:          File "<frozen importlib._bootstrap_external>", line 995, in exec_module
remote:          File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
remote:          File "/tmp/pip-build-env-ql62b47n/overlay/lib/python3.12/site-packages/setuptools/__init__.py", line 18, in <module>
remote:            from setuptools.extern.six import PY3, string_types
remote:        ModuleNotFoundError: No module named 'setuptools.extern.six'
remote:
remote:  !     Push rejected, failed to compile Python app.
remote:
remote:  !     Push failed

And this is my requirements.txt

certifi==2024.8.30
charset-normalizer==2.0.12
click==8.0.4
colorama==0.4.5
contextvars==2.4
dash==2.15.0
dash-core-components==2.0.0
dash-html-components==2.0.0
dash-table==5.0.0
Flask==2.0.3
gunicorn==21.2.0
idna==3.10
immutables==0.19
importlib-metadata==4.8.3
itsdangerous==2.0.1
Jinja2==3.0.3
MarkupSafe==2.0.1
nest-asyncio==1.6.0
numpy==1.19.5
packaging==21.3
pandas==1.1.5
plotly==5.18.0
pyparsing==3.0.7
python-dateutil==2.9.0.post0
pytz==2024.2
requests==2.27.1
retrying==1.3.4
six==1.16.0
tenacity==8.2.2
typing_extensions==4.1.1
urllib3==1.26.20
Werkzeug==2.0.3
zipp==3.6.0

I tried installing setuptools separately but it kept telling me that this requirement is already satisfied by site-packages.


Solution

  • It’s likely that the issue you’re encountering is due to incompatibilities between some of your packages and Python 3.12, which is used by default on Heroku. From what I understand, numpy=1.19.5 and pandas=1.1.5 are compatible only up to Python 3.9.

    Have you tried specifying python-3.9.18 in your runtime.txt file?