I am trying launch a Docker container that has as an entrypoint a python script that accepts a BBOX as an argument. I use a Bash script in order to automate the above.
Where the BBOX should be of this form: lonmin latmin lonmax latmax
Below is the Bash script
run.sh
#! /bin/bash while getopts ":a" option; do case "${option}" in a) bbox="${OPTARG}" ;; ?) printf "Illegal option: -%sn" "$OPTARG" >&2 exit 1 ;; esac done shift "$((OPTIND-1))" # For a bbox inquiry docker run -it <docker_image_name:tag> --rm --bbox="$bbox"
Where <docker_image_name:tag> is a docker image.
The arguments are passed into the following python script: core.py
. . . def parse_args(): parser = argparse.ArgumentParser( prog='core', usage='%(prog)s [options] path', description='Download EO Products.', epilog='Enjoy downloading! :)') parser.add_argument("--bbox", type=float, nargs=4, help="lonmin latmin lonmax latmax") return parser.parse_args() . . .
If I ran the following command it fails
./run.sh -a 3 33 5 40
and raises the following error:
argument –bbox: expected 4 arguments
NOTE!
The following command is successful and it wont raise any errors
python core.py --bbox 3 33 5 40
EDIT
The command ./run.sh -a "3 33 5 40"
passes the arguments as a single string.
Echoing the arguments in the Bash script:
echo -e "BBOX VALUE: $bboxn" Output > BBOX VALUE: 3.0 33.0 5.0 40.0 echo -e "BBOX VALUE WITH QUOTES: '$bbox'n" Output > BBOX VALUE WITH QUOTES: '3.0 33.0 5.0 40.0'
But it still raises the same error when it is passed to the python script.
Solution:
docker run -it <docker_image_name:tag> --rm --bbox $bbox
Advertisement
Answer
Based on the provided bash example, bbox="${OPTARG}"
is always going to be an empty string as getopts ":a"
defined a
to be a simple flag (refer to this answer and associated posting on that thread for additional help). Even if you define getopts ":a:"
such that -a
will then accept an argument, calling ./run.sh -a 3 33 5 40
will result in ${bbox}
having just 3
as the value (you can verify this yourself by echo
ing out the value e.g. echo "bbox=${bbox}"
) as again, it will only consume one argument. Essentially the Python program was being invoked with bbox flag set to a single empty string argument.
Since the arguments are going to be simple numbers without spaces, I will opt to pass them as a single quoted string in the bash version and then pass them unquoted to Python where its argparse
will be able to handle the arguments separately, i.e.
File: run.sh
#!/bin/bash while getopts ":a:" option; do case "${option}" in a) bbox="${OPTARG}";; ?) printf "Illegal option: -%sn" "$OPTARG" >&2 exit 1 ;; esac done shift "$((OPTIND-1))" echo "bash: bbox='${bbox}'" python core.py --bbox $bbox
File: core.py
import argparse def parse_args(): parser = argparse.ArgumentParser( prog='core', usage='%(prog)s [options] path', description='Download EO Products.', epilog='Enjoy downloading! :)') parser.add_argument("--bbox", type=float, nargs=4, help="lonmin latmin lonmax latmax") return parser.parse_args() if __name__ == '__main__': args = parse_args() print("python: args=%r" % args)
Execution:
$ # success $ bash run.sh -a "1 2 3 4" bash: bbox='1 2 3 4' python: args=Namespace(bbox=[1.0, 2.0, 3.0, 4.0]) $ # failure in python as bash did not consume all arguments (lack of quotes) $ bash run.sh -a 1 2 3 4 bash: bbox='1' usage: core [options] path core: error: argument --bbox: expected 4 arguments $ # failure in python due to insufficient arguments in quotes $ bash run.sh -a "1 2 3" bash: bbox='1 2 3' usage: core [options] path core: error: argument --bbox: expected 4 arguments $ # failure in bash $ bash run.sh -b "1 2 3 4" Illegal option: -b
If you must pass the arguments to bash as separate arguments (i.e. not a single quoted argument like in the above success example and as the first failure example due to lack of quotes), you will need to do one of the following suggestions found in the various answers in the following threads and adapt the script to pass the correct arguments to Python: