Reputation: 7341
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?
Upvotes: 17
Views: 18430
Reputation: 3077
If your use case is distributing a CLI for users who install your package then Lucas' answer is best.
But if you actually want to expose scripts with CLIs to run within your project then you'd be better off using a task runner that directly supports this. I am the author of a tool called PoeThePoet, which can be used to achieve this as a poetry plugin or stand-alone tool.
Declare a task in your pyproject.toml including the desired arguments:
[tool.poe.tasks.serve]
script = "my_pkg.app:serve(host, port)"
args = ["host", "port"]
This task can then be run as poetry poe serve --host 0.0.0.0 --port 8000
when using the poetry plugin.
Poe support most of the basic functionality of argparse, including aliases, positional argument, types, and default values for arguments. Check the docs for details.
Upvotes: 2
Reputation: 11679
This question is really two separate questions:
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.
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:
$ python 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).
poetry run
NOTE: In the v2.X versions of Poetry, arguments may work differently for poetry run
commands
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:
At the command-line, directly running the script:
$ poetry run python args.py arg1 arg2 arg3
Arg #0: <some_path>/args.py
Arg #1: arg1
Arg #2: arg2
Arg #3: arg3
Or, run it as a script, installed by Poetry. In this case the script name we assign is arg_script
, and you just run it directly at a terminal prompt with the virtual environment activated (i.e. do not invoke with python):
In pyproject.toml
:
[tool.poetry.scripts]
arg_script = 'args:start' # run start() function from ./args.py
After updating pyproject.toml
, run poetry install
at a terminal prompt to install the script in the virtual environment named as arg_script
.
With Poetry, you can run a command in the virtual environment by using poetry run
:
$ poetry run arg_script arg1 arg2 arg3
Arg #0: arg_script
Arg #1: arg1
Arg #2: arg2
Arg #3: arg3
Any arguments added after poetry run
, act just like you were typing them into a terminal that has the virtual environment already activated. i.e. The equivalent is:
$ poetry shell
$ args_script arg1 arg2 arg3
Upvotes: 12
Reputation: 7341
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?
Upvotes: 20