sloppyfrenzy
sloppyfrenzy

Reputation: 271

How do I run multiple executables in python one after the other

I'm still very new to Python and am still wrapping my head around everything it can do. I'm currently working on a small app to help me in my job. It's got a graphical menu that lets me choose apps to install on a PC. The problem I have is some of the buttons have two installers that they run (32 and 64 bit). I need the program to wait for one to be finished before starting the next one. How do I do this?

Here's the code...

def retranslateUi(self, Form):
    Form.setWindowTitle(_translate("Form", "Form", None))
    self.label.setText(_translate("Form", "What would you like to install?", None))
    self.adobe_reader.setText(_translate("Form", "Adobe Reader", None))
    self.flash.setText(_translate("Form", "Flash", None))
    self.java_7.setText(_translate("Form", "Java 7", None))
    self.java_8.setText(_translate("Form", "Java 8", None))
    self.adobe_reader.clicked.connect(self.adobe)
    self.flash.clicked.connect(self.flash13)
    self.java_7.clicked.connect(self.java7)
    self.java_8.clicked.connect(self.java8)

def adobe(self):
    os.startfile("C:\\Users\\Erik\\Desktop\\install_reader_11.exe")

def flash13(self):
    os.startfile("C:\\Users\\Erik\\Desktop\\install_flash_13_IE.exe")
    os.startfile("C:\\Users\\Erik\\Desktop\\install_flash_13_nonIE.exe")

def java7(self):
    os.startfile("C:\\Users\\Erik\\Desktop\\install_java-7u71-x32.exe")
    os.startfile("C:\\Users\\Erik\\Desktop\\install_java-7u71-x64.exe")

def java8(self):
    os.startfile("C:\\Users\\Erik\\Desktop\\install_java-8u25-x32.exe")
    os.startfile("C:\\Users\\Erik\\Desktop\\install_java-8u25-x64.exe")

Here's the edited code after I made the changes from Steve... also an error message I get in the python terminal after running an installer (which seems to work).

def adobe(mycmd):

    mycmd = r"C:\Users\Erik\Desktop\install_reader_11.exe"

    try:
        retcode = call(mycmd,shell = True)
        if retcode < 0:
            print >>sys.stderr, "Child was terminated by signal", -retcode
        else:
            print >>sys.stderr, "Child returned", retcode

    except OSError as e:
        print >>sys.stderr, "Execution failed:", e
        retcode = -1

    return retcode

def flash13(mycmd):

    mycmd = r"C:\Users\Erik\Desktop\install_flash_13_IE.exe"

    try:
        retcode = call(mycmd,shell = True)
        if retcode < 0:
            print >>sys.stderr, "Child was terminated by signal", -retcode
        else:
            print >>sys.stderr, "Child returned", retcode

    except OSError as e:
        print >>sys.stderr, "Execution failed:", e
        retcode = -1

    return retcode

Error Msg...

print >> sys.stderr, "Child returned", retcode
TypeError: unsupported operand type(s) for >>: 'builtin_function_or_method' and
'_io.TextIOWrapper'

Thanks!

Upvotes: 1

Views: 2974

Answers (2)

Cody Piersall
Cody Piersall

Reputation: 8547

Everywhere that you're using os.startfile(cmd) use subprocess.call(cmd). At the top of your script put

import subprocess

And change everywhere that has

os.startfile("C:\\Users\\Erik\\Desktop\\whatever.exe")

to

subprocess.call("C:\\Users\\Erik\\Desktop\\whatever.exe")

The problem with using os.startfile for your script is that it is not blocking. That means that your script does not wait for the user to interact with the installers that pop up; it just keeps going, and it can pop up several installers at once. subprocess.call is blocking. That means that it waits for whatever you launch to be finished, and your script will start right back up when the installer is closed.

Upvotes: 3

Steve Barnes
Steve Barnes

Reputation: 28370

Rather than os.startfile use something like the following example, I would put it into a function:

early in your code you need:

from subprocess import call

def SafeExtern(mycmd):
    """ Wrapper to call external programs checking the results """
    try: # This allows exceptions to be caught
        retcode = call(mycmd, shell=True) # Call the external program
        if retcode < 0: # Check the return code errors should be <0
            print >>sys.stderr, "Child was terminated by signal", -retcode
        else:
            print >>sys.stderr, "Child returned", retcode # For information
    except OSError as e: # Catch OSErrors and let the user know
        print >>sys.stderr, "Execution failed:", e
        retcode = -1 # Obviously this is an error
    return retcode

You can then use the above function to call external programs waiting for the result in each case.

Note that if you prefix each string with r you can get rid of the double backslashes, e.g.:

r"C:\Users\Erik\Desktop\install_java-7u71-x32.exe"

rather than

"C:\\Users\\Erik\\Desktop\\install_java-7u71-x32.exe"

Upvotes: 1

Related Questions