I want to write a function that will execute a shell command and return its output as a string, no matter, is it an error or success message. I just want to get the same result that I would have gotten with the command line.
What would be a code example that would do such a thing?
def run_command(cmd): # ?????? print run_command('mysqladmin create test -uroot -pmysqladmin12') # Should output something like: # mysqladmin: CREATE DATABASE failed; error: 'Can't create database 'test'; database exists'
Something like that:
def runProcess(exe): p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while(True): retcode = p.poll() #returns None while subprocess is running line = p.stdout.readline() yield line if(retcode is not None): break
Note, that I'm redirecting stderr to stdout, it might not be exactly what you want, but I want error messages also.
This function yields line by line as they come (normally you'd have to wait for subprocess to finish to get the output as a whole).
For your case the usage would be:
for line in runProcess('mysqladmin create test -uroot -pmysqladmin12'.split()): print line,
The answer to this question depends on the version of Python you're using. The simplest approach is to use the
>>> subprocess.check_output(['ls', '-l']) b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_output runs a single program that takes only arguments as input.1 It returns the result exactly as printed to
stdout. If you need to write input to
stdin, skip ahead to the
Popen sections. If you want to execute complex shell commands, see the note on
shell=True at the end of this answer.
check_output function works on almost all versions of Python still in wide use (2.7+).2 But for more recent versions, it is no longer the recommended approach.
If you're using Python 3.5 or higher, and do not need backwards compatibility, the new
run function is recommended. It provides a very general, high-level API for the
subprocess module. To capture the output of a program, pass the
subprocess.PIPE flag to the
stdout keyword argument. Then access the
stdout attribute of the returned
>>> import subprocess >>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE) >>> result.stdout b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
The return value is a
bytes object, so if you want a proper string, you'll need to
decode it. Assuming the called process returns a UTF-8-encoded string:
>>> result.stdout.decode('utf-8') 'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
This can all be compressed to a one-liner:
>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8') 'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
If you want to pass input to the process's
stdin, pass a
bytes object to the
input keyword argument:
>>> cmd = ['awk', 'length($0) > 5'] >>> input = 'foo\nfoofoo\n'.encode('utf-8') >>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=input) >>> result.stdout.decode('utf-8') 'foofoo\n'
You can capture errors by passing
stderr=subprocess.PIPE (capture to
stderr=subprocess.STDOUT (capture to
result.stdout along with regular output). When security is not a concern, you can also run more complex shell commands by passing
shell=True as described in the notes below.
This adds just a bit of complexity, compared to the old way of doing things. But I think it's worth the payoff: now you can do almost anything you need to do with the
run function alone.
If you are using an older version of Python, or need modest backwards compatibility, you can probably use the
check_output function as briefly described above. It has been available since Python 2.7.
It takes takes the same arguments as
Popen (see below), and returns a string containing the program's output. The beginning of this answer has a more detailed usage example.
You can pass
stderr=subprocess.STDOUT to ensure that error messages are included in the returned output -- but don't pass
check_output. It can cause deadlocks. When security is not a concern, you can also run more complex shell commands by passing
shell=True as described in the notes below.
If you need to pipe from
stderr or pass input to the process,
check_output won't be up to the task. See the
Popen examples below in that case.
If you need deep backwards compatibility, or if you need more sophisticated functionality than
check_output provides, you'll have to work directly with
Popen objects, which encapsulate the low-level API for subprocesses.
Popen constructor accepts either a single command without arguments, or a list containing a command as its first item, followed by any number of arguments, each as a separate item in the list.
shlex.split can help parse strings into appropriately formatted lists.
Popen objects also accept a host of different arguments for process IO management and low-level configuration.
To send input and capture output,
communicate is almost always the preferred method. As in:
output = subprocess.Popen(["mycmd", "myarg"], stdout=subprocess.PIPE).communicate()
>>> import subprocess >>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE, ... stderr=subprocess.PIPE) >>> out, err = p.communicate() >>> print out . .. foo
If you set
communicate also allows you to pass data to the process via
>>> cmd = ['awk', 'length($0) > 5'] >>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, ... stderr=subprocess.PIPE, ... stdin=subprocess.PIPE) >>> out, err = p.communicate('foo\nfoofoo\n') >>> print out foofoo
Note Aaron Hall's answer, which indicates that on some systems, you may need to set
stdin all to
DEVNULL) to get
communicate to work at all.
In some rare cases, you may need complex, real-time output capturing. Vartec's answer suggests a way forward, but methods other than
communicate are prone to deadlocks if not used carefully.
As with all the above functions, when security is not a concern, you can run more complex shell commands by passing
1. Running shell commands: the
Normally, each call to
check_output, or the
Popen constructor executes a single program. That means no fancy bash-style pipes. If you want to run complex shell commands, you can pass
shell=True, which all three functions support.
However, doing so raises security concerns. If you're doing anything more than light scripting, you might be better off calling each process separately, and passing the output from each as an input to the next, via
run(cmd, [stdout=etc...], input=other_output)
The temptation to directly connect pipes is strong; resist it. Otherwise, you'll likely see deadlocks or have to do hacky things like this.
2. Unicode considerations
check_output returns a string in Python 2, but a
bytes object in Python 3. It's worth taking a moment to learn about unicode if you haven't already.
This is way easier, but only works on Unix (including Cygwin).
import commands print commands.getstatusoutput('wc -l file')
it returns a tuple with the (return_value, output)
This only works in
python2.7: it is not available on
python3. For a solution that works in both, use the
subprocess module instead:
import subprocess output=subprocess.Popen(["date"],stdout=PIPE) response=output.communicate() print response
Vartec's answer doesn't read all lines, so I made a version that did:
def run_command(command): p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) return iter(p.stdout.readline, b'')
Usage is the same as the accepted answer:
command = 'mysqladmin create test -uroot -pmysqladmin12'.split() for line in run_command(command): print(line)
Your Mileage May Vary, I attempted @senderle's spin on Vartec's solution in Windows on Python 2.6.5, but I was getting errors, and no other solutions worked. My error was:
WindowsError: [Error 6] The handle is invalid.
I found that I had to assign PIPE to every handle to get it to return the output I expected - the following worked for me.
import subprocess def run_command(cmd): """given shell command, returns communication tuple of stdout and stderr""" return subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE).communicate()
and call like this, (
 gets the first element of the tuple,
After learning more, I believe I need these pipe arguments because I'm working on a custom system that uses different handles, so I had to directly control all the std's.
To stop console popups (with Windows), do this:
def run_command(cmd): """given shell command, returns communication tuple of stdout and stderr""" # instantiate a startupinfo obj: startupinfo = subprocess.STARTUPINFO() # set the use show window flag, might make conditional on being in Windows: startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW # pass as the startupinfo keyword argument: return subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, startupinfo=startupinfo).communicate() run_command('tracert 126.96.36.199')
Modern Python solution (>= 3.1):
res = subprocess.check_output(lcmd, stderr=subprocess.STDOUT)
If you need to run a shell command on multiple files, this did the trick for me.
import os import subprocess # Define a function for running commands and capturing stdout line by line # (Modified from Vartec's solution because it wasn't printing all lines) def runProcess(exe): p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) return iter(p.stdout.readline, b'') # Get all filenames in working directory for filename in os.listdir('./'): # This command will be run on each file cmd = 'nm ' + filename # Run the command and capture the output line by line. for line in runProcess(cmd.split()): # Eliminate leading and trailing whitespace line.strip() # Split the output output = line.split() # Filter the output and print relevant lines if len(output) > 2: if ((output == 'set_program_name')): print filename print line
Edit: Just saw Max Persson's solution with J.F. Sebastian's suggestion. Went ahead and incorporated that.
In Python 3.5:
import subprocess output = subprocess.run("ls -l", shell=True, stdout=subprocess.PIPE, universal_newlines=True) print(output.stdout)
This is a tricky but super simple solution which works in many situations:
import os os.system('sample_cmd > tmp') print open('tmp', 'r').read()
A temporary file(here is tmp) is created with the output of the command and you can read from it your desired output.
Extra note from the comments: You can remove the tmp file in the case of one-time job. If you need to do this several times, there is no need to delete the tmp.
I had a slightly different flavor of the same problem with the following requirements:
I've combined and tweaked previous answers to come up with the following:
import subprocess from time import sleep def run_command(command): p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) # Read stdout from subprocess until the buffer is empty ! for line in iter(p.stdout.readline, b''): if line: # Don't print blank lines yield line # This ensures the process has completed, AND sets the 'returncode' attr while p.poll() is None: sleep(.1) #Don't waste CPU-cycles # Empty STDERR buffer err = p.stderr.read() if p.returncode != 0: # The run_command() function is responsible for logging STDERR print("Error: " + str(err))
This code would be executed the same as previous answers:
for line in run_command(cmd): print(line)
I had the same problem But figured out a very simple way of doing this follow this
import subprocess Input = subprocess.getoutput("ls -l") print(Input)
Hope it helps out
Note: This solution is python3 specific as
subprocess.getoutput() don't work in python2
You can use following commands to run any shell command. I have used them on ubuntu.
import os os.popen('your command here').read()
eg, execute('ls -ahl') differentiated three/four possible returns and OS platforms:
def execute(cmd, output=True, DEBUG_MODE=False): """Executes a bash command. (cmd, output=True) output: whether print shell output to screen, only affects screen display, does not affect returned values return: ...regardless of output=True/False... returns shell output as a list with each elment is a line of string (whitespace stripped both sides) from output could be , ie, len()=0 --> no output; [''] --> output empty line; None --> error occured, see below if error ocurs, returns None (ie, is None), print out the error message to screen """ if not DEBUG_MODE: print "Command: " + cmd # https://stackoverflow.com/a/40139101/2292993 def _execute_cmd(cmd): if os.name == 'nt' or platform.system() == 'Windows': # set stdin, out, err all to PIPE to get results (other than None) after run the Popen() instance p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) else: # Use bash; the default is sh p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, executable="/bin/bash") # the Popen() instance starts running once instantiated (??) # additionally, communicate(), or poll() and wait process to terminate # communicate() accepts optional input as stdin to the pipe (requires setting stdin=subprocess.PIPE above), return out, err as tuple # if communicate(), the results are buffered in memory # Read stdout from subprocess until the buffer is empty ! # if error occurs, the stdout is '', which means the below loop is essentially skipped # A prefix of 'b' or 'B' is ignored in Python 2; # it indicates that the literal should become a bytes literal in Python 3 # (e.g. when code is automatically converted with 2to3). # return iter(p.stdout.readline, b'') for line in iter(p.stdout.readline, b''): # # Windows has \r\n, Unix has \n, Old mac has \r # if line not in ['','\n','\r','\r\n']: # Don't print blank lines yield line while p.poll() is None: sleep(.1) #Don't waste CPU-cycles # Empty STDERR buffer err = p.stderr.read() if p.returncode != 0: # responsible for logging STDERR print("Error: " + str(err)) yield None out =  for line in _execute_cmd(cmd): # error did not occur earlier if line is not None: # trailing comma to avoid a newline (by print itself) being printed if output: print line, out.append(line.strip()) else: # error occured earlier out = None return out else: print "Simulation! The command is " + cmd print ""