Barbarossa
Barbarossa

Reputation: 1193

How to execute command line in a python loop?

I am trying to determine the best way to execute something in command line using python. I have accomplished this with subprocess.Popen() on individual files. However, I am trying to determine the best way to do this many time with numerous different files. I am not sure if I should create a batch file and then execute that in command, or if I am simply missing something in my code. Novice coder here so I apologize in advance. The script below returns a returncode of 1 when I use a loop, but a 0 when not in a loop. What is the best approach for the task at hand?

def check_output(command, console):
    if console == True:
        process = subprocess.Popen(command)
    else:
        process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
    output, error = process.communicate()
    returncode = process.poll()
    return returncode, output, error

for file in fileList.split(";"):
    ...code to create command string...
    returncode, output, error = check_output(command, False)
    if returncode != 0:
        print("Process failed")
        sys.exit()

EDIT: An example command string looks like this:

C:\Path\to\executable.exe -i C:\path\to\input.ext -o C:\path\to\output.ext

Upvotes: 2

Views: 13776

Answers (4)

wils484
wils484

Reputation: 275

What your code is trying to accomplish is to run a command on a file, and exit the script if there's an error. subprocess.check_output accomplishes this - if the subprocess exits with an error code it raises a Python error. Depending on whether you want to explicitly handle errors, your code would look something like this:

file in fileList.split(";"):
    ...code to create command string...
    subprocess.check_output(command, shell=True)

Which will execute the command and print the shell error message if there is one, or

file in fileList.split(";"):
    ...code to create command string...
    try:
        subprocess.check_output(command,shell=True)
    except subprocess.CalledProcessError:
        ...handle errors...
        sys.exit(1)

Which will print the shell error code and exit, as in your script.

Upvotes: 0

wegry
wegry

Reputation: 8147

You might consider using subprocess.call

from subprocess import call

for file_name in file_list:
    call_args = 'command ' + file_name
    call_args = call_args.split() # because call takes a list of strings 
    call(call_args)

It also will output 0 for success and 1 for failure.

Upvotes: 0

merlin2011
merlin2011

Reputation: 75589

If you are merely running commands one after another, then it is probably easiest to cast aside Python and stick your commands into a bash script. I assume you merely want to check errors and abort if one of the commands fails.

#!/bin/bash

function abortOnError(){
    "$@"
    if [ $? -ne 0 ]; then
        echo "The command $1 failed with error code $?"
        exit 1
    fi
}

abortOnError ls /randomstringthatdoesnotexist
echo "Hello World" # This will never print, because we aborted

Update: OP updated his question with sample data that indicate he is on Windows. You can get bash for Windows through cygwin or various other packages, but it may make more sense to use PowerShell if you are on Windows. Unfortunately, I do not have a Windows box, but there should be a similar mechanism for error checking. Here is a reference for PowerShell error handling.

Upvotes: 0

h4unt3r
h4unt3r

Reputation: 844

Try using the commands module (only available before python 3)

>>> import commands
>>> commands.getstatusoutput('ls /bin/ls')
(0, '/bin/ls')

Your code might look like this

import commands

def runCommand( command ):
    ret,output = commands.getstatutoutput( command )
    if ret != 0:
        sys.stderr.writelines( "Error: "+output )
    return ret

for file in fileList.split(';'):
    commandStr = ""
    # Create command string
    if runCommand( commandStr ):
        print("Command '%s' failed" % commandStr)
        sys.exit(1)

You are not entirely clear about the problem you are trying to solve. If I had to guess why your command is failing in the loop, its probably the way you handle the console=False case.

Upvotes: 0

Related Questions