1

I would like to write a python code that run several functions sequentially. Actually, start from first function and check if it doesn't throw any error, then start running second function and so on. I used following strategy, but it didn't stop when first function throws error and keep running other function:

    try:
        firstFunc()
    except:
        raise ExceptionFirst('job failed!')
    else:
        try:
            secondFunc()
        except:
            raise ExceptionSecond('second function failed!')

------------------------------ ADD-ON-------------------------------------------

All functions defined in a separate way and don't have connection with each other. The structure of each function is like following (e.g., first fucntion):

p = subprocess.Popen("abaqus script=py.py", shell=True)
p.communicate() #now wait
if p.returncode == 0:
    print("job is successfully done!")

I changed my function as follows and it worked successfully:

p = subprocess.check_call("abaqus script=py.py", shell=True)
if p == 0:
    print("job is successfully done!")

But, I stuck with the same problem for one of my functions which has following structure:

p = subprocess.check_call("java -jar javaCode.jar XMLfile.xml", shell=True)
if p == 0:
    print("job is successfully done!")

It throws an error, but the python print out "job is successfully done!" for that and keeps running other functions!!

---------------------------------------- Full Code ------------------------------------------------

import subprocess
import sys, os

def abq_script():
    p = subprocess.check_call("abaqus script=py.py", shell=True)
    if p == 0:
        print("job is successfully done!\n")

def abq_java():
    p = subprocess.check_call("java -jar FisrtJavaCode.jar", shell=True)
    if p == 0:
        print("job is successfully done!\n")

def java_job():
    p = subprocess.check_call("java -jar secondJavaCode.jar XMLfile.xml", shell=True)
    if p == 0:
        print("job is successfully done!\n")

def abq_python_java():  
    funcs = [abq_script, abq_java, java_job]
    exc = Exception('job failed!')
    for func in funcs:
        try:
            func()
        except Exception as e:
            print(str(e))
            break

If the first or second function shows an error, the exception throws an exception and program stops from running. But, if last function (java_job) shows an error, program doesn't throw any exception and keeps running.

Siamak Malek
  • 45
  • 2
  • 11
  • @KasraAD what `if` statement.......? – Adam Smith Feb 17 '15 at 16:41
  • I meant from "check if it doesn't throw any error" was the exception part. – Siamak Malek Feb 17 '15 at 16:56
  • This one won't throw any exceptions. If you use `subprocess.check_call`, it will check the return code for you and raise a `CalledProcessError` exception if it's nonzero. – babbageclunk Feb 17 '15 at 18:01
  • @babbageclunk You mean using "p = subprocess.check_call()" instead of "p = subprocess.Popen()"? – Siamak Malek Feb 17 '15 at 18:26
  • @babbageclunk I've got your point, but in some cases your solution seems not working. I explained at the end of my question. – Siamak Malek Feb 17 '15 at 20:19
  • It's hard to tell what's going on here - I think you're getting confused between an exception in the current Python process, and the scripts you're running with subprocess printing an error and setting returncode to non-zero. Could you show the full code of the functions you're running, rather than just parts of the body? The version you show using subprocess.Popen will never throw an exception, even if the script it runs crashes and sets a nonzero return code. – babbageclunk Feb 18 '15 at 09:49
  • @babbageclunk I put full code in the original question. – Siamak Malek Feb 18 '15 at 16:59

2 Answers2

4

Put your functions into a list and iterate through them, calling each.

funcs = [firstFunc, secondFunc, ...]
for func in funcs:
    try:
        func()
    except ValueError: # Or whatever specific exception you want to handle...
        # Handle it...
        break

(See here for discussion of why it's far better to catch the specific exception you're trying to handle.)

Edit:

If each function has a specific set of exceptions that you'd like to catch, but it differs for the functions, you could put them into the list with the functions.

funcs = [
    (firstFunc, (ValueError, TypeError)),
    (secondFunc, (ZeroDivisionError, NameError)),
    # More function and their exceptions here...
]
for func, exceptions_to_catch in funcs:
    try:
        func()
    except exceptions_to_catch: 
        # Handle it...
        break

More edit:

I'd structure this differently - the only thing that differs between jobs is the command to run. You could do this with something like:

commands = [
    "abaqus script=py.py",
    "java -jar FisrtJavaCode.jar",
    "java -jar javaCode.jar XMLfile.xml",
]
for command in commands:
    subprocess.check_call(command, shell=True)
    print 'command {!r} successfully done!'.format(command)    

You don't need to catch the subprocess.CalledProcessError that might be thrown if one of the commands sets a nonzero return code - that'll stop processing the way you want.

Now it sounds like the underlying problem is that java -jar javaCode.jar XMLfile.xml doesn't set the return code correctly when it fails.

Community
  • 1
  • 1
babbageclunk
  • 8,523
  • 1
  • 33
  • 37
  • Thanks for your comment. I tried your solution, but it didn't break after first function throws an error.The problem is remains on exception type. It's not a fixed exception type and may vary with different input files or different functions. – Siamak Malek Feb 17 '15 at 16:59
  • Well, if you're genuinely in the situation that you can't control what kind of exception the functions you're calling will throw, get rid of the ValueError in the except clause. – babbageclunk Feb 17 '15 at 17:51
  • 1
    Even in that case, you should catch `except Exception` so you don't end up catching a `KeyboardInterrupt` or etc – Adam Smith Feb 17 '15 at 17:52
  • Also, each function may raise different exception in which I don't know all of them, because of this I used "raise exception". – Siamak Malek Feb 17 '15 at 18:14
  • @babbageclunk thank you very much for helping me, your last solution was very helpful. But, I still have problem with the last command, I don't know why? Another question, How can I manage some calculations between two commands, for example the last command may need some info (like some parameter calculation)? – Siamak Malek Feb 21 '15 at 06:33
  • The last command fails, and prints an error message, but it sets the returncode to 0. That means your driver program doesn't know that it failed. – babbageclunk Feb 23 '15 at 14:21
1

Why are you trying to try/except if you're only throwing another exception? Let the original exception bubble up if you're trying to stop execution thereafter.

firstFunc()
secondFunc()
thirdFunc()
we_all_about_the_funk()
Adam Smith
  • 52,157
  • 12
  • 73
  • 112
  • what do you mean "Let the original exception bubble up ..."? – Siamak Malek Feb 17 '15 at 17:15
  • If you can't handle an exception at the time, don't catch it. Let the calling scope catch it instead. – Adam Smith Feb 17 '15 at 17:18
  • I still have the same problem with using your solution. My second function throws an error, but the python keep running third function and so on. – Siamak Malek Feb 17 '15 at 17:32
  • @SiamakMalek You'll have to give us more information on how you're running the functions then, because when Python sees an uncaught exception it stops. My guess is that you have `firstFunc` calling `secondFunc` and etc from an earlier attempt to chain your function calls. – Adam Smith Feb 17 '15 at 17:38
  • I already edit my original post in order to show the function definition. – Siamak Malek Feb 17 '15 at 18:29
  • @SiamakMalek your posted code never throws an exception, so I'm not sure what you're expecting to happen...? – Adam Smith Feb 17 '15 at 18:32
  • My goal is to run some functions sequentially. If a function throws an error or an exception, program stops running and do not run other functions. If my code is disable to capture this goal, what should I do? – Siamak Malek Feb 17 '15 at 18:41
  • 1
    From this description, @AdamSmith's solution is the best. If one of the functions throw an exception, execution will stop. – babbageclunk Feb 18 '15 at 09:44