2

I have a central python script that calls various other python scripts and looks like this:

os.system("python " + script1 + args1)
os.system("python " + script2 + args2)
os.system("python " + script3 + args3)

Now, I want to exit from my central script if any of the sub-scripts encounter an error.

What is happening with current code is that let's say script1 encounters an error. The console will display that error and then central script will move onto calling script2 and so on.

I want to display the encountered error and immediately exit my central code.

What is the best way to do this?

Pratham Solanki
  • 337
  • 2
  • 5
  • 16
  • could you explain it more ? – anjaneyulubatta505 Feb 23 '18 at 07:16
  • @AnjaneyuluBatta My main script is calling various other scipts (as shown in the code snippet). So now if the first scipt1 encounters an error, even though that error is displayed, the code moves onto calling scipt2 and so on. – Pratham Solanki Feb 23 '18 at 07:17
  • Are these scripts supposed t run parallel to the main process? – Ubdus Samad Feb 23 '18 at 07:21
  • @UbdusSamad No. They are supposed to run sequentially. And the latter one is dependent on its previous one. So if I encounter an error in any script, it gets propagated through all the latter scripts. Hence I want to exit just as the first error is encountered. – Pratham Solanki Feb 23 '18 at 07:23

4 Answers4

1

You can try subprocess

import subprocess,sys

try:
    output = subprocess.check_output("python test.py", shell=True)
    print(output)
except ValueError as e:
    print e
    sys.exit(0)

print("hello world")
mkHun
  • 5,891
  • 8
  • 38
  • 85
1

Overall this is a terrible way to execute a series of commands from within Python. However here's a minimal way to handle it:

#!python
import os, system
for script, args in some_tuple_of_commands:
    exit_code = os.system("python " + script + args)
    if exit_code > 0:
        print("Error %d running 'python %s %s'" % (
            exit_code, script, args), file=sys.stderr)
        sys.exit(exit_code)

But, honestly this is all horrible. It's almost always a bad idea to concatenate strings and pass them to your shell for execution from within any programming language.

Look at the subprocess module for much more sane handling of subprocesses in Python.

Also consider trying the sh or the pexpect third party modules depending on what you're trying to do with input or output.

Jim Dennis
  • 17,054
  • 13
  • 68
  • 116
0

I don't know if it's ideal for you but enclosing these commands in a function seems a good idea to me:

I am using the fact that when a process exits with error os.system(process) returns 256 else it returns 0 as an output respectively.

def runscripts():
    if os.system("python " + script1 + args1):return(-1); #Returns -1 if script1 fails and exits.
    if os.system("python " + script2 + args2):return(-2); #Returns -2 and exits
    if os.system("python " + script3 + args3):return(-3); #Pretty obvious
    return(0)

runscripts()

#or if you want to exit the main program
if runscripts():sys.exit(0)
Ubdus Samad
  • 1,218
  • 1
  • 15
  • 27
0

Invoking the operating system like that is a security breach waiting to happen. One should use the subprocess module, because it is more powerful and does not invoke a shell (unless you specifically tell it to). In general, avoid invoking shell whenever possible (see this post).

You can do it like this:

import subprocess
import sys

# create a list of commands
# each command to subprocess.run must be a list of arguments, e.g.
# ["python", "echo.py", "hello"]
cmds = [("python " + script + " " + args).split()
        for script, args in [(script1, args1), (script2, args2), (script3,
                                                                  args3)]]


def captured_run(arglist):
    """Run a subprocess and return the output and returncode."""
    proc = subprocess.run( # PIPE captures the output
        arglist, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    return proc.stdout, proc.stderr, proc.returncode


for cmd in cmds:
    stdout, stderr, rc = captured_run(cmd)
    # do whatever with stdout, stderr (note that they are bytestrings)
    if rc != 0:
        sys.exit(rc)

If you don't care about the output, just remove the subprocess.PIPE stuff and return only the returncode from the function. You may also want to add a timeout to the execution, see the subprocess docs linked above for how to do that.

slarse
  • 19
  • 1
  • 4