1

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?

12
  • 1
    See this SO post. Mentions set -e as unreliable and bad practice. Your script may not necessarily reach the echo Commented Oct 14, 2015 at 18:07
  • Since you're using exit directly, try changing your import to from sys import exit. Commented Oct 14, 2015 at 18:16
  • I already read that post, and I know people suggest trap, but I'm not sure how to use it in my specific case. Commented Oct 14, 2015 at 18:17
  • @ray my understanding of sys.exit() in python is that it is intended for "applications", whereas exit() is for interactive shell (which is my case) Commented Oct 14, 2015 at 18:18
  • Your script terminates with local: can only be used in a function for me. Commented Oct 14, 2015 at 18:18

3 Answers 3

1

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

Sign up to request clarification or add additional context in comments.

3 Comments

I do this already though... I will update my post with the python script verbatim
You're using the built-in exit. Change your exit(1) to sys.exit(1) or do as @ray mentioned and add from sys import exit to the top of your script.
Why does it matter? I've read that both exit calls eventually call the same thing anyway. I tried them both in my experiments and I have not noticed a difference.
1

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.

5 Comments

Actually my bash code was a copy & paste from a function, I pieced it together for my question here. Small oversight, I will correct it. I'm not actually using local outside of a function in my real script thought.
A much better and more idiomatic approach would be python -c 'exit(1)' || echo "fail"
I'd recommend to pass on the error codes to the calling function also in your bash script and then slip out of the script according to it.
@tripleee I just wanted to make it more visible for the questioner how to pass a return value to the calling bash script...
@ferdy My bash script as I wrote it in my question is essentially testing for the same thing. My echo call returns 0, not 1.
0

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.

1 Comment

Again you're still missing my point. See the example I put here. Notice that the local keyword changes the behavior of being able to detect exit code. tutorialspoint.com/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.