'Pass commandline arguments to a Python script installed with Poetry

The poetry documentation says that the script section can be used to install scripts or executable when the package is installed. But it does not show any example of how to pass arguments to the script.

How can you do to receive with argparse the arguments in the function?



Solution 1:[1]

First a little project setup:

Starting from a new poetry project with poetry new example_script (and creating a main.py file inside example_script dir) with a structure like this:

??? example_script
?   ??? __init__.py
?   ??? main.py
??? pyproject.toml
??? README.rst
??? tests
    ??? __init__.py
    ??? test_poetry_example.py

And adding in the pyproject.toml the config (in the section [tool.poetry.scripts]) of the script that we are going to install:

# pyproject.toml

[tool.poetry]
name = "example_script"

# some lines excluded

[tool.poetry.scripts]
my-script = "example_script.main:start"

# some lines excluded

And finally the main.py file, which has to have a start function inside (as we passed it in the toml). The arguments parser goes inside this function, since this function is the one that will end up executing when we run the script:

import argparse


def some_function(target, end="!"):
    """Some example funcion"""
    msg = "hi " + target + end
    print(msg)


def start():
    # All the logic of argparse goes in this function
    parser = argparse.ArgumentParser(description='Say hi.')
    parser.add_argument('target', type=str, help='the name of the target')
    parser.add_argument('--end', dest='end', default="!",
                    help='sum the integers (default: find the max)')

    args = parser.parse_args()
    some_function(args.target, end=args.end)

We can run the script with poetry, or install and run it directly:

# run with poetry
$ poetry run my-script

# install the proyect (this will create a virtualenv if you didn't have it created)
$ poetry install
# activate the virtualenv
$ poetry shell
# run the script
$ my-script --help
usage: my-script [-h] [--end END] target

Say hi.

positional arguments:
  target      the name of the target

optional arguments:
  -h, --help  show this help message and exit
  --end END   sum the integers (default: find the max)


$ my-script "spanish inquisition" --end "?"
hi spanish inquisition?

Solution 2:[2]

This question is really two separate questions:

  1. How do I pass arguments into a script that is run using Poetry
  2. How do I access and parse those arguments, in particular, using argparse

The initial answer (by Lucas), addresses parts of each, especially about argparse, but I'm answering to fill in some additional details and explain how to directly access the args.

Access arguments directly in any function or script

As an alternative to argparse, arguments can be directly accessed in Python at any time using sys.argv, which is a list of strings, each one is one of the arguments. Python splits up the arguments based on spaces, unless the spaces are enclosed in quotes (either single or double quotes).

This method is more direct and lightweight than argparse, with a lot less functionality.

args.py setup as a main script file with a start() function:

import sys

def start(args=sys.argv):
  for i, arg in enumerate(args):
    print(f'Arg #{i}: {arg}')

if __name__ == '__main__':
  start()

Run it at the command-line with a variety of argument types:

$ py args.py "item 1" 'Hello Arguments!!' "i 3" 4 5 6
Arg #0: args.py
Arg #1: item 1
Arg #2: Hello Arguments!!
Arg #3: i 3
Arg #4: 4
Arg #5: 5
Arg #6: 6

The first argument is always the script that was called, in exactly the way it was called (i.e. relative or absolute path to the script file or other reference).

Adding arguments when calling with poetry run

While you can run scripts with Poetry by activating the virtual environment with poetry shell and then running the script as normal with python script.py arg1 arg2 arg3, you can also add arguments directly to the poetry run command:

In pyproject.toml:

[tool.poetry.scripts]
arg_script = 'args:start'

At a command-line, using poetry run:

$ poetry run arg_script arg1 arg2 arg3
Arg #0: arg_script
Arg #1: arg1
Arg #2: arg2
Arg #3: arg3

With poetry run, the first argument is the reference to the script that is in the pyproject.toml file, not the name of the script. In this case that was arg_script, even though the script is args.py.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Lucas
Solution 2 LightCC