Home > database >  how to pass bash getopts argument to Python script with getopt
how to pass bash getopts argument to Python script with getopt

Time:04-22

I have a bash script which takes a getopt argument, builds a Python getopt option and tries to run a Python script passing the created getopt argument. However, this doesn't work.

My bash script

#!/bin/bash
set -x 
set -e

while getopts "d:" o; do
    case "${o}" in
        d) 
            echo $OPTARG
            MY_DATETIME_PARAM="--my-date ${OPTARG}"
            ;;
    esac
done

python my_python_script.py "${MY_DATETIME_PARAM}"

And my_python_script.py

import getopt
import sys

try:
    opts, args = getopt.getopt(sys.argv[1:], "d:", ["my-date="])
except getopt.GetoptError as e:
    print(e)   
    sys.exit(1)    
    
for opt, arg in opts:
    if opt in ("-d", "--my-date"):
        print(arg)

And the result is

$ ./test.sh -d 2012-12-12
  set -e
  getopts d: o
  case "${o}" in
  echo 2012-12-12
2012-12-12
  MY_DATETIME_PARAM='--my-date 2012-12-12'
  getopts d: o
  python my_python_script.py '--my-date 2012-12-12'
option --my-date 2012-12-12 not recognized

However, running the python script manually from cmd seems to work nice

$ python my_python_script.py --my-date 2012-12-12
2012-12-12

CodePudding user response:

The problem is that you are quoting ${MY_DATETIME_PARAM} when calling python, which makes it a single string and a single argument instead of 2 separate arguments.

One way to solve this is to remove the quotes in the last line:

python my_python_script.py ${MY_DATETIME_PARAM}

That should work in this case, but is not very robust. A better way to do this is to store the arguments in an array, and then expand the elements of the array in the last line, like this:

declare -a parameters
while getopts "d:" o; do
  case "${o}" in
    d) 
      echo $OPTARG
      parameters =( "--my-date" "${OPTARG}" )
            ;;
  esac
done

python my_python_script.py "${parameters[@]}"

You can then easily add parameters by adding to the array.

It is important to note that the array expansion in the last line is quoted. This ensures that spaces in the array elements are handled correctly. The shell interprets the quotation marks as meaning: "Quote each element of the array", rather than "Quote all elements after expansion". For example:

> parameters=( "Hello" "Bon jour" "Auf wiedersehen, Pet" )

> echo ${parameters[@]}
Hello Bon jour Auf wiedersehen, Pet

> echo "${parameters[@]}"
"Hello" "Bon jour" "Auf wiedersehen, Pet"

Even though the array only contains 3 strings, the first echo results in 6 separate strings containing no spaces. The second echo gives the correct result. 3 strings, some containing spaces.

CodePudding user response:

You need three changes :

declare -a MY_DATETIME_PARAM
...
              MY_DATETIME_PARAM=(--my-date "${OPTARG}")
...
python my_python_script.py "${MY_DATETIME_PARAM[@]}"
  • Related