2

Is there any way to get the list of packages specified in the install_requires parameter to the setup command (in setup.py)?

I'm looking for something similar to pip show pkgname | grep -i requires, but for local packages (and that reports version specifiers and filters).

The real task I'm solving is to check if versions specified in setup.py and requirements.txt have diverged, so if there is a tool that can do this directly...?

5
  • 1
    Could you clarify what you mean my "diverged"? setup.py and requirements.txt are for quite different tasks, setup.py has only the direct dependencies (possible with bounds for constraints) whereas requirements.txt has all the transitive dependencies too, and pinned to exact versions. Commented Jan 26, 2023 at 18:42
  • @wim e.g. when we've found that we need a specific version on older pythons, we would put "attrs==21.4.0 ; python_version < '3.9'", "attrs>=22 ; python_version >= '3.9'" in the setup.py file, mirroring the requirements.txt file. If a new version is released that works universally it would be best to keep the setup.py file in sync with requirements.txt (which is used in CI). Commented Jan 26, 2023 at 18:55
  • 1
    There is no setup.py command for this as far as I know, and setuptools no longer wants to be in the business of providing a command line interface, so it won't ever happen. Maybe importlib.metadata.requires can help? However, it does require the package to be installed (there are some hackarounds to trick it into thinking a package is installed if you need) Commented Jan 26, 2023 at 19:46
  • By the way, I don't think one should ever pin in setup.py ever conditional for older Python versions. That's over-constraining the metadata, and as soon as something else in the dependency tree tries to constrain attrs suddenly you have a conflict and the package can't be installed at all. You can specifically exclude known broken versions using != instead. Commented Jan 26, 2023 at 19:46
  • importlib.metadata.requires is perfect, I see your point about pinning in setup.py also. Thanks for all your help :-) Commented Jan 26, 2023 at 19:55

1 Answer 1

2

For installed packages, use stdlib importlib.metadata.requires. Python 3.8+ is required, but there is a backport importlib-metadata for older Python versions. This is the easy case, because installed packages have already generated the metadata (including dependency specs) at installation time. For local source trees which aren't necessarily installed, read on.

There is a way to do this in Python APIs via distutils (which setuptools wraps):

import distutils.core
dist = distutils.core.run_setup("setup.py")
for req in dist.install_requires:
    print(req)

As a shell command that might look like:

python -c 'import distutils.core; print(*distutils.core.run_setup("setup.py").install_requires, sep="\n")'

It is also possible to use the CLI to generate egg-info and then read deps from that:

python setup.py egg_info
cat myproject.egg-info/requires.txt

However, distutils is deprecated and setuptools is trying to be a library only, so using setup.py in this way is quite neglected.

You might consider moving to declarative dependencies specified in pyproject.toml and then just reading the requirements directly with a simple TOML parser.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.