Home > other >  Run Docker container and passing a single option with multiple arguments to a python script
Run Docker container and passing a single option with multiple arguments to a python script

Time:08-18

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: -%s\n" "$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: $bbox\n"
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 

CodePudding user response:

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 echoing 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: -%s\n" "$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:

  • Related