Search code examples
pythonpython-poetry

Troubleshooting 'distribution not found' pkg_resources with Poetry


I am building a cli application, in which I am using poetry and pyproject.toml to define my application's version:

[tool.poetry]
name = "fili"
version = "0.1.0"
description = "My super awesome program."
authors = ["Jacob Pavlock <jtpavlock@gmail.com>"]
license = "MIT"

Now, I'd like to programatically access this version number in the CLI for my application, so I added the following code to cli.py

import argparse
import pkg_resources


def main():
    """Run our cli."""
    VERSION = pkg_resources.get_distribution("fili").version

    fili_parser = argparse.ArgumentParser(description="Run fili.")
    fili_parser.add_argument(
        "--version", action="version", version="%(prog)s {0}".format(VERSION)
    )


if __name__ == "__main__":
    main()

However, when run, I get the following error:

$ ./fili/cli.py 
Traceback (most recent call last):
  File "./fili/cli.py", line 22, in <module>
    main()
  File "./fili/cli.py", line 11, in main
    VERSION = pkg_resources.get_distribution("fili").version
  File "/home/jacob/.cache/pypoetry/virtualenvs/fili-yAte7WxV-py3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 481, in get_distribution
    dist = get_provider(dist)
  File "/home/jacob/.cache/pypoetry/virtualenvs/fili-yAte7WxV-py3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 357, in get_provider
    return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0]
  File "/home/jacob/.cache/pypoetry/virtualenvs/fili-yAte7WxV-py3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 900, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/home/jacob/.cache/pypoetry/virtualenvs/fili-yAte7WxV-py3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 786, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'fili' distribution was not found and is required by the application

For reference, my project directory structure

$ tree
.
├── fili
│   ├── cli.py
│   ├── __init__.py
│   └── __pycache__
│       ├── cli.cpython-38.pyc
│       └── __init__.cpython-38.pyc
├── fili.egg-info
│   ├── dependency_links.txt
│   ├── PKG-INFO
│   ├── SOURCES.txt
│   └── top_level.txt
├── LICENSE
├── poetry.lock
├── pyproject.toml
└── README.md

I have installed my package with poetry install, but what else am I missing?


Solution

  • You have to make sure that the environment that poetry installed it into when you ran poetry install is also the one that is executed when you run ./fili/cli.py. The latter command will just grab whatever is registered as the system's python binary to run your script, while poetry install will try to install it into whichever virtual environment is activated - or create a new one if none is.

    To solve this issue, you can 1) run poetry shell in order to activate the virtual environment that poetry used, after which a call like fili/cli.py will use the activated python, or you 2) delegate the call explicitly with poetry run fili/cli.py instead.


    If this didn't solve the problem, there are two other issues that might be the cause. The first is that you're using pkg_resources with python3.8. You shouldn't do that, the standard library was extended with importlib.metadata.version, which is just a straight upgrade.

    And finally, running part of an installed package as a script (read, directly executing a .py file instead of, say, a module: python -m fili) is a bit unsafe. It might mess up imports in confusing ways, which is usually solved by defining entrypoints for scripts.