Poetry brings a simplified interface to Python’s packaging and distribution system. It makes all the right things easy to do.
Here’s how you use it to develop a new Python CLI project.
We’ll make a CLI called
hello-snake, in a package and project called
poetry new to create the project skeleton.
tom@tomtop 🎪:~/tmp % poetry new snake Created package snake in snake
The resulting directory tree:
tom@tomtop 🎪:~/tmp % tree snake snake ├── README.rst ├── pyproject.toml ├── snake │ └── __init__.py └── tests ├── __init__.py └── test_snake.py
Change to the
snake project directory. Poetry will manage a virtualenv for
the project, tied to the project path and Python version. Create the
virtualenv and open a pre-activated shell with
tom@tomtop 🎪:~/tmp % cd snake tom@tomtop 🎪:~/tmp/snake % poetry shell Creating virtualenv snake--jYlyyG6-py3.8 in /Users/tom/Library/Caches/pypoetry/virtualenvs Spawning shell within /Users/tom/Library/Caches/pypoetry/virtualenvs/snake--jYlyyG6-py3.8 tom@tomtop 🎪:~/tmp/snake % . /Users/tom/Library/Caches/pypoetry/virtualenvs/snake--jYlyyG6-py3.8/bin/activate (snake--jYlyyG6-py3.8) tom@tomtop 🎪:~/tmp/snake %
Our CLI entrypoint will be in the
snake.console module. Create it in
snake/console.py, next to
snake/__init__.py, and add a
run() function to
serve as entrypoint.
def run(): print("🐍")
Our project will ship a single executable, named
hello-snake. Add it to the
tool.poetry.scripts section of
[tool.poetry.scripts] hello-snake = 'snake.console:run'`
This specifies that the program
hello-snake executes the function
Install the package and its dependencies to the virtualenv.
(snake--jYlyyG6-py3.8) tom@tomtop 🎪:~/tmp/snake % poetry install Updating dependencies Resolving dependencies... (0.2s) Writing lock file Package operations: 9 installs, 0 updates, 0 removals ... - Installing snake (0.1.0)
You can now run the new CLI as
(snake--jYlyyG6-py3.8) tom@tomtop 🎪:~/tmp/snake % hello-snake 🐍
snake package is installed to the virtualenv as “editable”, so that
changes made in the project source directory are reflected immediately whenever
hello-snake. To try that out, let’s make the snake a little angrier.
def run(): print("🐍 tsssssss")
hello-snake includes the change without having to re-install our package:
(snake--jYlyyG6-py3.8) tom@tomtop 🎪:~/tmp/snake % hello-snake 🐍 tsssssss
All of this should continue to work the next time you open a
poetry shell for
Packaging and distribution
It’s easy to share and distribute your new CLI package. Use
poetry build to
create tarball and wheel packages under
tom@tomtop 🎪:~/tmp/snake % poetry build Building snake (0.1.0) - Building sdist - Built snake-0.1.0.tar.gz - Building wheel - Built snake-0.1.0-py3-none-any.whl
The wheel file can be distributed to users, to be installed to their global Python environment:
tom@tomtop 🎪:~/tmp/snake % pip install --user dist/snake-0.1.0-py3-none-any.whl Processing ./dist/snake-0.1.0-py3-none-any.whl Installing collected packages: snake Successfully installed snake-0.1.0 WARNING: You are using pip version 19.2.3, however version 20.0.2 is available. You should consider upgrading via the 'pip install --upgrade pip' command.
Once the wheel is installed, the users can run
tom@tomtop 🎪:~/tmp/snake % hello-snake 🐍 tsssssss