[TOC]
Getting input and shelling out are both fairly normal tasks for programs that have to interact with a user or the operating system.
argparse to get command line parameters
import sys
import argparse
parser = argparse.ArgumentParser()
parser.add_argument( '-V', '--verbose', help='increase output verbosity', action="store_true" ) # make it a boolean type
parser.add_argument( 'number', help='squares a number', type=int )
args = parser.parse_args()
if args.verbose:
print '{0} {1} * {1}'.format( sys.argv[0], args.number )
print args.number**2
# python example.py 2 # output 4
# python example.py --verbose 2 # output 2 * 2 , 4 # boolean optional parameter
# action="count" # count the number of times the argument is used, e.g. -VV , args.verbose == 2
# parser.add_argument( "-V", "--verbosity", action="count", default=0, help='increase output verbosity' )
# group = parser.add_mutually_exclusive_group()
# group.add_argument( "-V", "--verbose", action="store_true" )
# group.add_argument( "-q", "--quiet", action="store_true" )
subprocess to send commands to the shell
import subprocess
mystrings = list()
mystrings.append( 'ls' ) # normal stuff just in single quotes
mystrings.append( '-ahl' ) # normal stuff just in single quotes
mystrings.append( 'name with space.txt' ) # multiple items together if they require escaping in the shell
p = subprocess.Popen( mystrings )
check_call( ['ls', '-l'] ) # convenience wrapper that returns True if the exit code was 0, otherwise raise CalledProcessError
p = subprocess.Popen( mystrings )
(stdout_data,stderr_data) = p.communicate() # tuple returns
# Popen.stdin If the stdin argument was PIPE, this attribute is a file object that provides input to the child process. Otherwise, it is None.
# Popen.stdout If the stdout argument was PIPE, this attribute is a file object that provides output from the child process. Otherwise, it is None.
# Popen.stderr If the stderr argument was PIPE, this attribute is a file object that provides error output from the child process. Otherwise, it is None.
subprocess call wrapper
from subprocess import call
import time
try:
while True:
call( ["ls", "-l"] ) # subprocess.call is a blocking wrapper of Popen
time.sleep( 2 )
except KeyboardInterrupt:
pass
print '\ndone'
- - -
from subprocess import Popen, PIPE
data = Popen(['/usr/bin/dpkg', "-l"], stdout=PIPE).communicate()[0]
# print len(data)
lines = data.split('ii')
print len(lines)
for i in lines:
if "ssl" in i:
print i.strip()
keyword = ''
output = Popen(['ps', '-ef'], stdout=PIPE).communicate()[0]
lines = output.split('\n')
for i in lines:
if keyword in i:
print i.strip()
from subprocess import Popen, PIPE
# get process listing but exclude vi
keyword = 'someapp'
exclude = 'vi'
output = Popen(['ps', '-ef'], stdout=PIPE).communicate()[0]
# print output
lines = output.split('\n')
# print len(lines)
targets = list()
for i in lines:
if keyword in i:
parts = i.strip().split()
excluded = False
for k in parts:
if k.strip() == exclude:
excluded = True
if not excluded:
targets.append(i.strip())
for i in targets:
print i
subprocess Popen replacing shell pipes and os.system()
output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0] # replace shell `
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) # replace shell |
output = p2.communicate()[0]
p = Popen("mycmd" + " myarg", shell=True) # replace os.system()
sts = os.waitpid(p.pid, 0)[1]
try:
retcode = call("mycmd" + " myarg", shell=True) # better replacement of os.system()
if retcode < 0:
print >>sys.stderr, "Child was terminated by signal", -retcode
else:
print >>sys.stderr, "Child returned", retcode
except OSError, e:
print >>sys.stderr, "Execution failed:", e
- - -
#!/usr/bin/env python
# search $PATH for python executable environment to run this script
import os
import sys
import subprocess
def get_result( command ):
""" Send a command to the os shell and get the result as a string. """
stringList = command.rsplit()
# for word in stringList:
# print word # DEBUG
# print ""
p = subprocess.Popen( stringList , shell = True , stdout = subprocess.PIPE )
linesum = ""
while True:
inline = p.stdout.readline()
if not inline:
break
linesum += inline
return linesum
if __name__ == '__main__':
print "{} arguments passed in: {}".format( len(sys.argv) , sys.argv )
print "type in a command like 'echo hi' "
test = sys.stdin.readline()
result = get_result( test )
sys.stdout.write( result )
print "your command result output saved as a string printed again: " , result
sys.stdout.flush()
print ""
subprocess sending a command to bash -c
import sys
import os
import subprocess
cmd = ['/usr/bin/sudo', '/bin/bash', '-c', 'touch /root/foobar']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
my_output, err = p.communicate()
print(my_output)
print(err)
argparse examples
#!/usr/bin/env python
import argparse
parser = argparse.ArgumentParser()
# SIMPLEST EXAMPLE
# parser.parse_args()
# ./example.py test # returns: usage example.py [-h] , unrecognized arguments: test
# SIMPLE EXAMPLE
# parser.add_argument( 'number', help='squares a number', type=int ) # default type is string
# args = parser.parse_args()
# print args.number**2
# OPTIONAL ARGUMENT EXAMPLE
parser = argparse.ArgumentParser()
parser.add_argument( '-V', '--verbose', help='increase output verbosity' )
parser.add_argument( 'number', help='squares a number', type=int )
args = parser.parse_args()
if args.verbose:
print '{0} * {0}'.format( args.number )
print args.number**2
# ./example.py # output usage: parser.py [-h] [-V VERBOSE] number , example.py: error: too few arguments
# ./example.py 2 # output 4
# ./example.py -V=true 2 # output 2 * 2 , 4
# ./example.py -V 1 2 # output 2 * 2 , 4
# ./example.py --verbose=foo 2 # output 2 * 2 , 4
# ./example.py --verbose 1 2 # output 2 * 2 , 4
Miscellaneous argparse and subprocess examples
import argparse
import time
import sys
import os
import subprocess
if __name__ == '__main__': # only currently works on win7?
try:
start_time = time.time()
parser = argparse.ArgumentParser( description='Process some integers.' )
parser.add_argument( 'integers' , metavar = 'N' , type = int , nargs = '+' , help = 'an integer for the accumulator' )
parser.add_argument( '--sum' , dest = 'accumulate' , action = 'store_const' , const = sum , default = max ,
help = 'sum the integers (default: find the max)' )
args = parser.parse_args()
print args.accumulate( args.integers )
print "type in a command like 'echo hi' "
user_input = sys.stdin.readline()
stringList = user_input.rsplit()
i = 0
for word in stringList: # DEBUG
print "%s word" % i
i = i + 1
p = subprocess.Popen( stringList , shell = True , stdout = subprocess.PIPE )
linesum = ""
while True:
inline = p.stdout.readline()
if not inline:
break
linesum += inline
print "On linux stdout readline isn't working, otherwise this prints 'hi' , " , str( linesum )
elapsed_time = time.time() - start_time
print "Hi World! Done in %s seconds \n" % elapsed_time
except KeyboardInterrupt, e: # Ctrl-C
raise e
- - -
# usage: python myappcfg.py , only currently works on win7
import argparse
import os
from subprocess import call
def main( **kwargs ):
if( kwargs ):
for key, value in kwargs.iteritems():
print "key=" + str( key ) + " value=" + str( value )
# cmd = '{0} {1}'.format(kwargs['program'], ' '.join(kwargs['infiles']))
# os.path.splitunc( path ) # for network shares
root = os.path.splitdrive( os.getcwd() )[0] # first element of the list
if( root == "" ):
print "linux system " , os.name
root = os.path.join( root , os.path.sep )
# print "root is " + root # DEBUG
if( os.name == "nt" ):
appengine_directory = os.path.join( root , "progra~2" , "google" , "google_appengine" )
# ~2 is the 32bit x86 program files in dos compatible path mode (no spaces in names)
print appengine_directory
appengine_script = os.path.join( appengine_directory , "appcfg.py" )
print "executing: python " + appengine_script # DEBUG
# call( ["python" , str( appengine_script ) ] )
if __name__ == "__main__":
try:
parser = argparse.ArgumentParser( description = 'appcfg.py action application_name' )
parser.add_argument( '--command' , type = str , help = 'appcfg action command' )
parser.add_argument( '--application_name' , type = str , help = 'application name' )
# parser.add_argument( 'application' , type = str , help = 'application name' )
args = parser.parse_args()
main( **vars(args) ) # sends arguments to main as a key value pair dictionary
except KeyboardInterrupt, e: # Ctrl-C
raise e
- - -
# Assumes: sudo pip install pip2pi s3cmd; sudo pip2tgz /tmp jasmine
# downloads: jasmine-2.0.0.tar CherryPy-3.2.5.tar.gz etc.
# s3cmd --config $HOME/.s3cfg put /tmp/index.html s3://mybucket/python/simple/PACKAGE/index.html
# expects all the directories are created, TODO: s3cmd createdir
import os
import subprocess
packages = list()
for i in os.listdir('/tmp'):
if os.path.isfile(i) and i.endswith('tar.gz'):
packages.append(i)
packages.sort()
print len(packages)
for i in packages:
package_name_parts = i.rsplit('-',1) # covers a package name like pytest-cov-1.6.tar.gz
package_name = package_name_parts[0]
with open('/tmp/index.html', 'w') as f:
print f.write('<a href="' + i + '">' + i + '</a><br />')
myargs = '/usr/bin/s3cmd ls s3://mybucket/python/simple/' + package_name + '/'
# myargs = '/usr/bin/s3cmd put ' + i + ' s3://mybucket/python/simple/' + package_name + '/'
print myargs
command_list = myargs.split()
p = subprocess.Popen(command_list, stdout=subprocess.PIPE)
my_data, my_err = p.communicate()
print my_data