`
standalone
  • 浏览: 595929 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

python subprocess

阅读更多

Module: subprocess
Purpose: Spawn and communicate with additional processes.
Python Version: New in 2.4

An updated version of this article can be found on the main PyMOTW site.

Description:

The subprocess module provides a consistent interface to creating and working with additional processes. It offers a higher-level interface than some of the other available modules, and is intended to replace functions such as os.system, os.spawn*, os.popen*, popen2.* and commands.*. To make it easier to compare subprocess with those other modules, this week I will re-create earlier examples using the functions being replaced.

The subprocess module defines one class, Popen() and a few wrapper functions which use that class. Popen() takes several arguments to make it easier to set up the new process, and then communicate with it via pipes. I will concentrate on example code here; for a complete description of the arguments, refer to section 17.1.1 of the library documentation.

A Note About Portability

The API is roughly the same, but the underlying implementation is slightly different between Unix and Windows. All of the examples shown here were tested on Mac OS X. Your mileage on a non-Unix OS will vary.

Running External Command

To run an external command without interacting with it, such as one would do with os.system(), Use the call() function.

import subprocess

# Simple command
subprocess.call('ls -l', shell=True)


$ python replace_os_system.py
total 16
-rw-r--r--   1 dhellman  dhellman     0 Jul  1 11:29 __init__.py
-rw-r--r--   1 dhellman  dhellman  1316 Jul  1 11:32 replace_os_system.py
-rw-r--r--   1 dhellman  dhellman  1167 Jul  1 11:31 replace_os_system.py~



And since we set shell=True, shell variables in the command string are expanded:

# Command with shell expansion
subprocess.call('ls -l $HOME', shell=True)


total 40
drwx------   10 dhellman  dhellman   340 Jun 30 18:45 Desktop
drwxr-xr-x   15 dhellman  dhellman   510 Jun 19 07:08 Devel
drwx------   29 dhellman  dhellman   986 Jun 29 07:44 Documents
drwxr-xr-x   44 dhellman  dhellman  1496 Jun 29 09:51 DownloadedApps
drwx------   55 dhellman  dhellman  1870 May 22 14:53 Library
drwx------    8 dhellman  dhellman   272 Mar  4  2006 Movies
drwx------   11 dhellman  dhellman   374 Jun 21 07:04 Music
drwx------   12 dhellman  dhellman   408 Jul  1 01:00 Pictures
drwxr-xr-x    5 dhellman  dhellman   170 Oct  1  2006 Public
drwxr-xr-x   15 dhellman  dhellman   510 May 12 15:19 Sites
drwxr-xr-x    5 dhellman  dhellman   170 Oct  5  2005 cfx
drwxr-xr-x    4 dhellman  dhellman   136 Jan 23  2006 iPod
-rw-r--r--    1 dhellman  dhellman   204 Jun 18 17:07 pgadmin.log
drwxr-xr-x    3 dhellman  dhellman   102 Apr 29 16:32 tmp



Reading Output of Another Command

By passing different arguments for stdin, stdout, and stderr it is possible to mimic the variations of os.popen().

Reading from the output of a pipe:

print '\nread:'
proc = subprocess.Popen('echo "to stdout"',
                       shell=True,
                       stdout=subprocess.PIPE,
                       )
stdout_value = proc.communicate()[0]
print '\tstdout:', repr(stdout_value)



Writing to the input of a pipe:

print '\nwrite:'
proc = subprocess.Popen('cat -',
                       shell=True,
                       stdin=subprocess.PIPE,
                       )
proc.communicate('\tstdin: to stdin\n')



Reading and writing, as with popen2:

print '\npopen2:'

proc = subprocess.Popen('cat -',
                       shell=True,
                       stdin=subprocess.PIPE,
                       stdout=subprocess.PIPE,
                       )
stdout_value = proc.communicate('through stdin to stdout')[0]
print '\tpass through:', repr(stdout_value)



Separate streams for stdout and stderr, as with popen3:

print '\npopen3:'
proc = subprocess.Popen('cat -; echo ";to stderr" 1>&2',
                       shell=True,
                       stdin=subprocess.PIPE,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE,
                       )
stdout_value, stderr_value = proc.communicate('through stdin to stdout')
print '\tpass through:', repr(stdout_value)
print '\tstderr:', repr(stderr_value)



Merged stdout and stderr, as with popen4:

print '\npopen4:'
proc = subprocess.Popen('cat -; echo ";to stderr" 1>&2',
                       shell=True,
                       stdin=subprocess.PIPE,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.STDOUT,
                       )
stdout_value, stderr_value = proc.communicate('through stdin to stdout\n')
print '\tcombined output:', repr(stdout_value)



Sample output:

read:
       stdout: 'to stdout\n'

write:
       stdin: to stdin

popen2:
       pass through: 'through stdin to stdout'

popen3:
       pass through: 'through stdin to stdout'
       stderr: ';to stderr\n'

popen4:
       combined output: 'through stdin to stdout\n;to stderr\n'



All of the above examples assume a limited amount of interaction. The communicate() method reads all of the output and waits for child process to exit before returning. It is also possible to write to and read from the individual pipe handles used by the Popen instance. To illustrate this, I will use this simple echo program which reads its standard input and writes it back to standard output:

import sys

sys.stderr.write('repeater.py: starting\n')

while True:
   next_line = sys.stdin.readline()
   if not next_line:
       break
   sys.stdout.write(next_line)
   sys.stdout.flush()

sys.stderr.write('repeater.py: exiting\n')



Make note of the fact that repeater.py writes to stderr when it starts and stops. We can use that to show the lifetime of the subprocess in the next example. The following interaction example uses the stdin and stdout file handles owned by the Popen instance in different ways. In the first example, a sequence of 10 numbers are written to stdin of the process, and after each write the next line of output is read back. In the second example, the same 10 numbers are written but the output is read all at once using communicate().

import subprocess

print 'One line at a time:'
proc = subprocess.Popen('repeater.py',
                       shell=True,
                       stdin=subprocess.PIPE,
                       stdout=subprocess.PIPE,
                       )
for i in range(10):
   proc.stdin.write('%d\n' % i)
   output = proc.stdout.readline()
   print output.rstrip()
proc.communicate()

print
print 'All output at once:'
proc = subprocess.Popen('repeater.py',
                       shell=True,
                       stdin=subprocess.PIPE,
                       stdout=subprocess.PIPE,
                       )
for i in range(10):
   proc.stdin.write('%d\n' % i)

output = proc.communicate()[0]
print output



Notice where the "repeater.py: exiting" lines fall in the output for each loop:

$ python interaction.py
One line at a time:
repeater.py: starting
0
1
2
3
4
5
6
7
8
9
repeater.py: exiting

All output at once:
repeater.py: starting
repeater.py: exiting
0
1
2
3
4
5
6
7
8
9



Signaling Between Processes

In part 4 of the series on the os module I included an example of signaling between processes using os.fork() and os.kill(). Since each Popen instance provides a pid attribute with the process id of the child process, it is possible to do something similar with subprocess. For this example, I will again set up a separate script for the child process to be executed by the parent process.

import os
import signal
import time

def signal_usr1(signum, frame):
   "Callback invoked when a signal is received"
   pid = os.getpid()
   print 'Received USR1 in process %s' % pid

print 'CHILD: Setting up signal handler'
signal.signal(signal.SIGUSR1, signal_usr1)
print 'CHILD: Pausing to wait for signal'
time.sleep(5)



And now the parent process:

import os
import signal
import subprocess
import time

proc = subprocess.Popen('signal_child.py')
print 'PARENT: Pausing before sending signal...'
time.sleep(1)
print 'PARENT: Signaling %s' % proc.pid
os.kill(proc.pid, signal.SIGUSR1)



And the output should look something like this:

$ python signal_parent.py
CHILD: Setting up signal handler
CHILD: Pausing to wait for signal
PARENT: Pausing before sending signal...
PARENT: Signaling 4124
Received USR1 in process 4124



Conclusions

As you can see, subprocess can be much easier to work with than fork, exec, and pipes on their own. It provides all of the functionality of the other modules and functions it replaces, and more. The API is consistent for all uses and many of the extra steps of overhead needed (such as closing extra file descriptors, ensuring the pipes are closed, etc.) are "built in" instead of being handled by your code separately.

References:

Python Module of the Week
Sample code
PyMOTW: os (Part 2)
PyMOTW: os (Part 4)

分享到:
评论

相关推荐

    基于 python subprocess 实现的定时任务系统源码.zip

    python subprocess 实现的定时任务系统源码.zip基于 python subprocess 实现的定时任务系统源码.zip基于 python subprocess 实现的定时任务系统源码.zip基于 python subprocess 实现的定时任务系统源码.zip基于 ...

    python subprocess 杀掉全部派生的子进程方法

    下面小编就为大家带来一篇python subprocess 杀掉全部派生的子进程方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    Python subprocess模块功能与常见用法实例详解

    本文实例讲述了Python subprocess模块功能与常见用法。分享给大家供大家参考,具体如下: 一、简介 subprocess最早在2.4版本引入。用来生成子进程,并可以通过管道连接他们的输入/输出/错误,以及获得他们的返回值。...

    对Python subprocess.Popen子进程管道阻塞详解

    今天小编就为大家分享一篇对Python subprocess.Popen子进程管道阻塞详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

    Python subprocess模块常见用法分析

    本文实例讲述了Python subprocess模块常见用法。分享给大家供大家参考,具体如下: subprocess模块是python从2.4版本开始引入的模块。主要用来取代 一些旧的模块方法,如os.system、os.spawn*、os.popen*、commands....

    python subprocess模块.docx

    在Python中,我们通过标准库中的subprocess包来fork一个子进程,并运行一个外部的程序。 subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所以我们可以根据需要来从中选取一个使用...

    Python Subprocess模块原理及实例

    如果由subprocess去执行系统命令的时候并不会让主进程去执行,而是主进程会开辟出一个子进程去执行,并不会影响到主进程的运行,主进程该干嘛就干嘛,那么又有个问题,大家都知道进程之间的内存空间是独立的,也就是...

    Python subprocess模块详细解读

    本文研究的主要是Python subprocess模块的相关内容,具体如下。 在学习这个模块前,我们先用Python的help()函数查看一下subprocess模块是干嘛的: DESCRIPTION This module allows you to spawn processes, connect...

    python-subprocess32-3.2.6-7.el7.x86_64.rpm

    官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装

    Python库 | subprocess_connection-0.0.4.tar.gz

    资源分类:Python库 所属语言:Python 资源全名:subprocess_connection-0.0.4.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    Python subprocess库的使用详解

    主要介绍了Python subprocess库的使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    Python如何通过subprocess调用adb命令详解

    本文主要给大家介绍了关于使用Python通过subprocess调用adb命令,subprocess包主要功能是执行外部命令(相对Python而言)。和shell类似。 换言之除了adb命令外,利用subprocess可以执行其他的命令,比如ls,cd等等...

    sac_scripts_pythonsac_pythonsac脚本_python处理地震_python调用sac_sac_

    在python中调用地震学处理程序sac的脚本,可以较为方便的处理目录下的sac文件

    python控制台输入密码

    python控制台输入密码,控制台输入密码变成`*`,支持删除等操作.

Global site tag (gtag.js) - Google Analytics