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?
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.