0

I have a python script that is called by a korn shell script. If the python script runs into an error, the korn shell script still exits with 0. How to a get the python script to tell the ksh that it didn't terminate correctly?

The rapper script looks like this:

python2.7 python_script.py ${inargument} >> ${log_file}  2>&1

exit_code=$?                             

if [ ${exit_code} -ne 0 ]
   then
   echo "Python script failed" >> ${log_file}
fi
Alex Kinman
  • 2,437
  • 8
  • 32
  • 51
  • 1
    In shell script you can do `echo "Returncode=$?"` – Walter A Apr 19 '16 at 18:16
  • Can you show your shell script? If the last command of the shell script runs the Python script, the shell should exit with the same exit status as the Python script on error. (If you have anything after the Python script's invocation, ie. a logging statement in your shell, then it could be that line's exit status being returned instead). – Charles Duffy Apr 19 '16 at 20:41
  • @CharlesDuffy I added the details of the shell script. It supposed to capture the exit state of the .py script but I seem to be omitting something. – Alex Kinman Apr 19 '16 at 21:30
  • 1
    @AlexKinman, that looks fine on the shell side. To test, try replacing `python2.7 python_script.py` with `python2.7 -c 'raise Exception("foo")'` -- if your shell script suddenly sees a nonzero exit status, you know it's the Python code that's masking the true exit status. – Charles Duffy Apr 19 '16 at 21:42
  • 1
    @AlexKinman, ...well, "fine" is a stretch; it's bad practice to capture exit status when that's all you're testing; it's better practice to write that like so: `if ! python2.7 python_script.py ...; then echo "Python script failed"; fi`, not capturing `$?` at all. But if the Python script is masking its exit status, that won't work either. – Charles Duffy Apr 19 '16 at 21:44
  • btw, instead of putting `>> ${log_file}` at the end of every command, it's more efficient to put `exec >>"$log_file"` (possibly with the `2>&1` as well) once at the top of your script, which will do the redirection permanently; that way you're not re-opening the file a bunch of separate times. – Charles Duffy Apr 19 '16 at 22:01
  • 1
    Voting to close as unreproducible. A standard Python installation returns a non-zero exit status on exception. `python -c 'raise ValueError("boom"); echo $?` prints `1` and `python -c 'import time; time.sleep(3600)'` when interrupted by ctrl-C likewise returns an exit status of `1`. Perhaps your `python2.7` command is an incompetently written wrapper which discards the exit status. – tripleee Apr 20 '16 at 04:26
  • @AlexKinman, if you `git clone` https://gist.github.com/charles-dyfis-net/1814662403f716784b32ce3ac6305496, and run `ksh test.ksh` in the directory that creates, do your results not contain "Python script failed"? – Charles Duffy Apr 20 '16 at 20:26
  • @CharlesDuffy I do get the "Python script failed" – Alex Kinman Apr 20 '16 at 20:51
  • @AlexKinman, ...which is what you'd hope for and expect, if your shell script is successfully retrieving the Python script's nonzero exit status. Can you update your test case to show a situation where it *doesn't* do that? – Charles Duffy Apr 20 '16 at 20:58
  • @tripleee I solved the problem and it was with another script downstream. Thanks for all the help. The question can be closed. – Alex Kinman Apr 22 '16 at 01:30
  • @AlexKinman, ...as its creator, you should be able to delete the question yourself -- that we don't need to wait for three more folks to vote. – Charles Duffy Apr 22 '16 at 01:31
  • @CharlesDuffy the answers below still have some useful information, which would disappear if I deleted the question (not for my benefit - but for others searches), am I correct? – Alex Kinman Apr 22 '16 at 01:54
  • 1
    I'm not sure that there's content here that isn't covered more tersely and directly in answers to narrower questions (and which is thus likely to be easier to find by folks it's of interest to). For instance, http://stackoverflow.com/questions/14259660/handling-exit-code-returned-by-python-in-shell-script; http://stackoverflow.com/questions/25728287/capturing-python-processs-exit-status-in-unix-shell; etc. – Charles Duffy Apr 22 '16 at 02:53
  • @CharlesDuffy It's not letting me delete the question because it has answers already. – Alex Kinman Apr 22 '16 at 16:31
  • Ahh -- those rules tend to change over time and with rep levels, so it's hard to track what they are for everyone. We'll presumably get a fifth close vote soon enough. – Charles Duffy Apr 22 '16 at 16:43

3 Answers3

4

I'm not sure about KSH, but this is how you get python to return a non-zero return value, I assume KSH can detect and deal with that.

import sys

retCode = 5
sys.exit(retCode)

or

retCode = -128
raise SystemExit(retCode)
nephlm
  • 543
  • 3
  • 11
  • 1
    `-128` isn't valid here -- it's unsigned single-byte integers only, so this will be converted to something else rather than returned intact. – Charles Duffy Apr 19 '16 at 20:31
  • ...also, ksh's behavior is precisely the same as that of any other POSIX-compliant shell in this respect, populating `$?` with the prior command's exit status. – Charles Duffy Apr 19 '16 at 20:32
  • (as an aside, see `man 3 sysexits` for a list of conventional exit status codes; custom values should, by convention, be below the `EX__BASE` constant of 64 -- and, for an erroneous status, above `0` (the `EXIT_SUCCESS` constant defined in C99). – Charles Duffy Apr 19 '16 at 20:35
0

Wrap your whole script in a try block and in catch write the error to an out put file. Than in your ksh you can go read that output file and do what ever it is you need to do.

here is some pseudo code.

rm opFile
python yourSript.py
if opFile != blank:
   process log file... 
   start cat runlog.m | more
kpie
  • 9,588
  • 5
  • 28
  • 50
  • Oh this didn't work for you? – kpie Apr 19 '16 at 18:12
  • I can't speak for the first downvoter, but speaking for myself, it's not a question of whether or not it works: There's a standard-practice way to do this, and ignoring that convention (defined in the C99 standard, in the POSIX standard, and elsewhere) for no good reason is... well, not good practice. – Charles Duffy Apr 19 '16 at 20:38
  • + @nephlm provided the best answer, in a use case where ksh wants to use python to fail gracefully, potentially trying multiple things before failing, creating a runlog file that documents the path through the execution is standard practice as far as I know... (The thing is I don't know.) – kpie Apr 20 '16 at 17:28
  • Yes, logging is standard practice. No, using that logged content in place of exit status is not standard practice. – Charles Duffy Apr 20 '16 at 20:22
0

I could not comment because of reputation, but you absolutely could use the code from nephim comment.

1) just put the first of nephim's code in test.py (chmod 700 test.py)

2) this ksh script run test.py :

#!/usr/bin/ksh

./test.py

exit $?

3) And this is example from command line

> ./test.ksh 
> echo $?
5

P.S.: You should chmod 700 test.ksh as well.

P.P.S : Probably I misunderstood your question. If your python script exits before it reach the end (and so it don't execute sys.exit(codeRet) command), in this case you should use try..execpt construction.

try :
    <some code>
except <Error to Catch>:
    sys.exit(codeRet)

As explained here : Python: about catching ANY exception you could even catch all of exceptions :

try:
    do_something()
except:
    print "Caught it!"

But as explained : "You can but you shouldn't"

Update: @AlexKinman I think there is some problem with your python... as mentioned by tripleee could it be some wrapper? Could you give a return of which python2.7

Here my tests :

$# cat wrong_test.ksh

#!/bin/ksh

log_file=log.txt

python -c 'raise Exception("foo")' >> ${log_file}  2>&1

exit_code=$?                             

if [ ${exit_code} -ne 0 ]
   then
   echo "Python script failed" >> ${log_file}
fi

$# cat log.txt Traceback (most recent call last): File "", line 1, in Exception: foo Python script failed

$# cat good_test.ksh

#!/bin/ksh

log_file=log1.txt

python -c 'print "Hello"' >> ${log_file}  2>&1

exit_code=$?                             

if [ ${exit_code} -ne 0 ]
   then
   echo "Python script failed" >> ${log_file}
fi

$# cat log1.txt
Hello

Community
  • 1
  • 1
Paul Zakharov
  • 515
  • 2
  • 15
  • If the interpreter exits due to an exception, it'll have a nonzero exit status by default -- you don't need to catch that and call `sys.exit()` yourself. – Charles Duffy Apr 19 '16 at 20:39
  • ...you can test this yourself easily: `python -c 'raise Exception("foo")'; echo $?` – Charles Duffy Apr 19 '16 at 20:40
  • @CharlesDuffy the problem I am not getting the nonzero default exit status. When I run the code in my python interpreter, I get an error if I pass the wrong input arguments. But when I run in using the KSH, it doesn't pass anything to the KSH. – Alex Kinman Apr 20 '16 at 00:26
  • @CharlesDuffy... yes, you are right. In this light, catch all to send just sys.exit(1) does not make sens... Except of situation if you are using exit status 1 for something in your code. In this case it could be intresting to catch and send another status. – Paul Zakharov Apr 20 '16 at 15:05
  • @AlexKinman, did you run the test I proposed? If you haven't, you don't know if the problem is in your Python or your shell; if it's the former, this question -- as a whole -- is asking the wrong thing. – Charles Duffy Apr 20 '16 at 18:56
  • @CharlesDuffy I did and it seems the problem is in the shell, not the python. – Alex Kinman Apr 20 '16 at 20:18
  • @AlexKinman, ...can you amend the question to show how to reproduce that determination? I haven't been able to repro that behavior; neither has triplee; neither (as I understand it) has Paul (in light of their most recent comment in this thread). – Charles Duffy Apr 20 '16 at 20:21
  • @CharlesDuffy yes, for me it return the good return codes : $> python -c 'raise Exception("foo")'; echo $? Traceback (most recent call last): File "", line 1, in Exception: foo 1 -------------------- $> python -c 'print "Hello"'; echo $? Hello 0 So if there is an Exception I have code 1 Without exception code 0 – Paul Zakharov Apr 21 '16 at 09:06
  • @AlexKinman, ...in light of the above, could you amend to provide explicit reproduction steps, so someone else can use the same code and reach the same determination (as to the shell's behavior being at fault)? – Charles Duffy Apr 21 '16 at 14:42
  • 1
    @CharlesDuffy I figured out the problem. The Python was working fine and the KSH was working fine, but another KSH downstream from it had a bug such that it was making my code look like it wasn't working correctly, when it actually was. Thanks for the help. – Alex Kinman Apr 22 '16 at 01:29