I have this python3 program. It sets error code 0 when it works and non-zero when it fails. It puts the good message into stdout and the failure string into stderr. I think it’s well-behaved.
#! /bin/python3
import sys
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
cs = sys.argv[1]
if str(cs) == "1":
print("GOOD")
else:
eprint("BAD")
sys.exit(1)
See how I test it:
$ X=`python3 example.py 1`; echo It is: $X
It is: GOOD
$ X=`python3 example.py 0`; echo It is: $X
BAD
It is:
I have this bash program that calls the python program:
#! /bin/bash
function do_example() {
local DB=$1
local URI=`python3 example.py $DB`
RESULT=$?
if [ $RESULT -eq 0 ]; then
echo $URI
echo success
else
echo $URI
echo failed
fi
}
do_example 1
do_example 0
It runs a python program first. Captures the stdout. Then it checks the return value. It doesn’t work. It should say success and then failed. Instead, it says success both times. It doesn’t work. It doesn’t handle the error code correctly.
$ ./example.sh
success
BAD
success
$ ./example.sh
GOOD
success
BAD
The generalized question is how to collect the stdout into a local variable and act on the error code at the same time?
>Solution :
local‘s exit code overrides the one from the command substitution. To work around this, always split apart local declarations from assignments if the assignments could fail:
local URI
URI=`python3 example.py $DB`
RESULT=$?
By the way, you don’t need to save the exit code in a variable if you check it in the if statement. Also, it’s best to avoid uppercase variable names as they could clash with built-in names. Finally, I recommend using $(...) in place of backticks; it is easier to nest substitutions.
local db=$1
local uri
if uri=$(python3 example.py "$db"); then
echo "$uri"
echo success
else
echo failed
fu