void.pointer
void.pointer

Reputation: 26345

Propagate python script exit code to calling shell script

I have the following in a python script (using python 3.4), if there is any failure:

exit(1)

The purpose of this python script is to print() some value, so that it may be assigned to a shell variable like so:

#!/bin/bash
set -e
result=$(python my-script.py)
echo $?

However, if the script fails, the echo above returns 0. I want set -e to immediately interrupt and fail the script if the python script fails (i.e. returns non zero exit code).

How can I make this work? I tried set -eo pipefail as well in my bash script and I've noticed no difference.

I'm running Ubuntu 15.

EDIT

My python script (verbatim) just in case it is the suspect here...

import re
import sys

version_regex = r'(?:(?:release|hotfix)\/|^)([\d.]+)-\d+-g[a-f\d]+$'

result = re.search(version_regex, sys.argv[1])
if not result:
    exit(1)

print(result.group(1))

Note that I have tried both sys.exit(1) and exit(1) in my experiments but I never saw my bash script fail.

EDIT 2

parsed_version=$(python parse-git-describe.py $describe_result; echo $?)
echo $parsed_version
echo $?

The above bash script gives me the following output:

1
0

Note that the script parse-git-describe.py is the same as the python script provided earlier.

EDIT 3

Apparently local causes this to break. EDIT 2 above was wrong, that is the result with local inside a shell function:

foo()
{
    local parsed_version=$(python parse-git-describe.py $describe_result; echo $?)
    echo $parsed_version
    echo $?
}

Result is:

1
0

But if I remove local it works fine?

foo()
{
    parsed_version=$(python parse-git-describe.py $describe_result; echo $?)
    echo $parsed_version
    echo $?
}

Result is:

1
1

Why does local matter?

Upvotes: 1

Views: 2446

Answers (3)

code_dredd
code_dredd

Reputation: 6085

Why does local matter??

The local keyword specifies the variable's scope. The following sample script should illustrate:

#!/bin/bash
HELLO=Hello    # global variable, HELLO

function hello {
    local HELLO=World   # local variable with same name; diff scope
    echo $HELLO         # this is the local, not global!
}

echo $HELLO  # print global
hello        # function call!
echo $HELLO  # global unchanged!

Running this code from the shell (placed in test.sh script) produces:

➜  Projects  ./test.sh
Hello
World
Hello

When you use local, the variable and the exit code it had go out of scope when the function returns to the caller. Your function should return the value to the caller if you don't want that to happen.

Upvotes: 0

ferdy
ferdy

Reputation: 7716

The local can only be used within a function in bash. (So your bash script code above doesn't work either.)

Why don't you call your python script in the bash script and check the return value and then jump out of your script if necessary?

$ python -c "exit(0)"
$ [ $? == 0 ] || echo "fail"
$ python -c "exit(1)"
$ [ $? == 0 ] || echo "fail"
fail

You can easily adapt this in your shell script, I guess.

Upvotes: 1

aganders3
aganders3

Reputation: 5945

You can to set the exit code if you finish your script by calling sys.exit(code).

Upvotes: 1

Related Questions