Manuel Yguel
Manuel Yguel

Reputation: 368

How to organize a python project with poetry for a command line script

When doing a poetry init I got the following structure:

/packagename
  __init__.py
  packagename.py
 /packagename
  /tests
   __init__.py
   test_packagename.py
pyproject.toml

which is fine for a package but I do not see how to make it fit a command line script. When I have a script like script.py with the following code structure:

In file script.py:

#!/usr/bin/python3

def main():
  print("Ok")

if __name__ == '__main__':
  main()

It is not intended to be used as a python module however, it may have dependencies and tests that are interesting to be handle with poetry.

In some example it is shown that with the following poetry syntax:

[tool.poetry.scripts]
cli_script = 'script.py:main'

then one can call the script with:

poetry run cli_script

I am looking for some guideline on howto organize properly my poetry project for such usage.

I have looked for option for poetry init (like poetry init --script) for instance. But it seems that kind of use case was not covered in the new/init poetry options.

Upvotes: 13

Views: 15293

Answers (2)

indigo
indigo

Reputation: 29

Alternatively you can run:

poetry run python3 script.py

where:

  • script.py is the name of the file having python code.
  • python3 is the python executable inside the poetry virtual environment. This can be python as well, depending on the python version you have. You may confirm the same using poetry run python3 -V or poetry run python -V, before executing the above command.

This command can be used in crontab as well to schedule simple scripts.

Upvotes: 2

finswimmer
finswimmer

Reputation: 15202

By "poetry init" I guess you mean poetry new. But also then your structure looks a bit weird. I would suggest the following structure:

packagename
├── packagename
│   ├── __init__.py
│   └── cli.py
├── tests
│   ├── __init__.py
│   └── test_packagename.py
└── pyproject.toml

The pyproject.toml looks like this:

[tool.poetry]
name = "packagename"
version = "0.1.0"
description = ""
authors = ["finswimmer <[email protected]>"]

[tool.poetry.scripts]
cli_script = "packagename.cli:main"

[tool.poetry.dependencies]
python = "^3.6"

[tool.poetry.dev-dependencies]
pytest = "^5.2"

[build-system]
requires = ["poetry>=1.0"]
build-backend = "poetry.masonry.api"

You cli.py as in your example:

#!/usr/bin/python3

def main():
  print("Ok")

if __name__ == '__main__':
  main()

After a poetry install you can run poetry run cli_script.

Upvotes: 17

Related Questions