5

I have a shell script calling Python inside it.

#! /bin/bash

shopt -s extglob
echo "====test===="
~/.conda/envs/my_env/bin/python <<'EOF'

import sys
import os


try:
    print("inside python")
    x = 2/0
except Exception as e:
    print("Exception: %s" % e)
    sys.exit(2)
print("at the end of python")
EOF
echo "end of script"

If I execute this, the lines below still get printed.

"end of script"

I want to exit the shell in the exception block of the python script and let the script not reach EOF

Is there a way to create and kill a subprocess in the except block above, that will kill the entire shell script?

Can I spawn a dummy subprocess and kill it inside the exception block there by killing the entire shell script?

Any examples would be helpful. Thanks in advance.

8
  • Just save the return value from the line you call python and check it after EOF Commented Jul 24, 2018 at 13:56
  • 1
    or have non-zero return code status exit your shell (set -e). Also don't do sys.exit(-1). Exit codes are positive. to be portable respect range 0-255 Commented Jul 24, 2018 at 13:58
  • @Jean-FrançoisFabre I don't want to set -e because I want some of the errors to silently fail and proceed in the script, but specifically this python exception to kill the entire script. Thanks, won't use -1, edited the post. Commented Jul 24, 2018 at 14:01
  • 1
    this question isnt a duplicate.... Commented Jul 24, 2018 at 14:02
  • 1
    The question was how to exit the script based on what the python script does, as reiterated by the asker. Commented Jul 24, 2018 at 14:04

3 Answers 3

3

From the shell script you have 2 options:

  • set -e: all errors quit the script
  • check python subcommand return code, abort if non-zero

(maybe more details here: Aborting a shell script if any command returns a non-zero value?)

Now, if you don't want to change the handling from your shell script, you could get the parent process of the python script and kill it:

except Exception as e:
    import os,signal,sys
    print("Exception: %s" % e)
    os.kill(os.getppid(),signal.SIGTERM)
    sys.exit(2)

if you need this on windows, this doesn't work (os.kill doesn't exist), you have to adapt it to invoke taskkill:

subprocess.call(["taskkill","/F","/PID",str(os.getppid())])

Now I would say that killing the parent process is bad practice. Unless you don't control the code of this parent process, you should try to handle the exit gracefully.

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

3 Comments

Thanks! Doesn't os.kill take 2 parameters, other one being sig?
Thanks, this is what I exactly wanted. Much cleaner and nicer. Works like a charm.
I would not call that cleaner, but if you have 300 shell scripts, you probably don't want to modify them all, so this is the solution to change only in the python script. This only works if called directly by the shell BTW.
3

The whole EOF ... EOF block gets executed within the Python runtime so exiting from it doesn't affect the bash script. You'll need to collect the exit status and check it after the Python execution if you want to stop the further bash script progress, i.e.:

#!/bin/bash

~/.conda/envs/my_env/bin/python <<'EOF'
import sys

sys.exit(0x01)  # use any exit code from 0-0xFF range, comment out for a clean exit

print("End of the Python script that will not execute without commenting out the above.")
EOF

exit_status=$?  # store the exit status for later use

# now lets check the exit status and see if python returned a non-zero exit status
if [ $exit_status -ne 0 ]; then
    echo "Python exited with a non-zero exit status, abort!"
    exit $exit_status  # exit the bash script with the same status
fi
# continue as usual...
echo "All is good, end of script"

Comments

0

One way to kill the entire script could be to save the PID and then using Python's system commands to execute a kill command on the PID when the exception happens. If we imported 'os' it would be something along the lines of:

# In a shell
PID=$$
...
// Some Python Exception happens
os.system('kill -9' + $PID)

Comments

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.