Overview
There are many ways but I am going to discuss two popular methods to do it.
- os.system
- subprocess.Popen
os.system
It executes the string command in subshell by calling the standard C function i.e. system(). It has some limitations like Changes to sys.stdin etc. are not reflected in the environment of the executed command. It only returns the exit code.
0 – exit code 0 means the command runs successfully.
Non 0 – exit code other than 0 means command produced some error.
Note:- On Unix, the return value is the exit status of the process encoded in the format specified for the wait method. On Windows, the return value is returned by the system shell.
Syntax:
os.command(cmd);
Example: Run a OS command
import os
p=os.system("ls -l")
print(p)
subprocess module
So when you want the output of the command then you use the subprocess module. It has inbuilt various methods like call, Popen which comes with greater capabilities.
subprocess.Popen – Execute a child program in a new process.
This module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their outputs, errors, and return codes.
Syntax:
class subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout
=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=Non
e, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
- args – Sequence of program arguments or a single string
- bufsize – Increase bufsize in case of experience performance issues, You can set bufsize to either -1 or a large enough positive value (such as 4096).
- preexec_fn – This object will be called in the child process just before the child is executed. (Unix only)
- close_fds(True/False) – if True, Close all file descriptors except 0, 1 and 2 before the child process is executed. (Unix only). Note that on Windows, you cannot set close_fds to true
- cwd – Change current working directory of the child’s process.
- env – If you don’t want to inherit the current process’s environment, which is the default behavior then use this param to pass the environment to the child process.
- universal_newlines (True/False) – If True, then stderr and stout will be treated in universal newlines.
Note: Passing shell=True can be a security hazard and also need shell-type formatting before running the command, so be cautious.
Example 1: Read the output of the command:
import subprocess
cmd="uname"
'''
subprocess.PIPE - Special value that can be used as the
stdin, stdout or stderr argument to Popen and indicates
that a pipe to the standard stream should be opened.
'''
#calling method with OS command
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
output = process.stdout.read().strip()
error = process.stderr.read().strip()
process.communicate()
exit_code = process.returncode
#you can process the output like below
if len(output) > 0:
print('Output : {}'.format(output))
#you can pprocess the error like below.
if len(error) > 0:
print('Error : {}'.format(error))
#you can take decision ased on command succcess or failureofthe command like below
print('Exit Code : {}'.format(exit_code))
if exit_code != 0:
raise Exception('Error executing command: {}. Exit Code: {}, Stdout: `{}`, Stderr: `{}`'.format(
' '.join(command_components), exit_code, output, error)
Example 2: We can pass command with arguments in a list
p = subprocess.Popen(["p4", "login", "-s"], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
p.communicate()
if p.returncode != 0:
sys.exit('Error: not logged into Perforce');
Example 3: We can pass command in a string directly.
p = subprocess.Popen("git ls-files", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
sys.exit('Error: could not get repo files - %s' % stderr)