python多进程调⽤模块内函数_python⼦进程模块subprocess
详解与应⽤实例之⼀
分类: Python/Ruby
2014-09-09 10:59:42
subprocess--⼦进程管理器
⼀、subprocess 模块简介
subprocess最早是在2.4版本中引⼊的。
subprocess模块⽤来⽣成⼦进程,并可以通过管道连接它们的输⼊/输出/错误,以及获得它们的返回值。
它⽤来代替多个旧模块和函数:
os.system
os.spawn*
os.popen*
popen2.*
commands.*
关于这个模块可以取代的旧函数可以参见 subprocess-replacements ⼀节。
POSIX⽤户(Linux, BSD, etc)还可以安装和使⽤更新的subprocess32模块来代替python 2.7版本中的subprocess.
subprocess32虽然是⼀个低版本,但在有些情况下效果更好。
1.1. 使⽤ subprocess模块
启动⼦进程的推荐⽅式是使⽤下⾯的便利功能。
当这些还不能满⾜需求时,就需要使⽤底层的Popen接⼝。
1. subprocess.call
语法:
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
语义:
运⾏由args指定的命令,直到命令结束后,返回 返回码的属性值。
上⾯的参数是最常见的⽅式,下⾯是⽰例代码:
>>>
>>> subprocess.call(["ls", "-l"])
>>> subprocess.call("exit 1", shell=True)
1
WARNING: 使⽤ shell=True 是⼀种安全保护机制。
NOTE: 在使⽤这个函数时,不要使⽤ stdout=PIPE 或 stderr=PIPE 参数,
不然会导致⼦进程输出的死锁。
如果要使⽤管道,可以在 communicate()⽅法中使⽤Popen
⽰例代码:
import subprocess
rc = subprocess.call(["ls","-l"])
可以通过⼀个shell来解释⼀整个字符串:
import subprocess
out = subprocess.call("ls -l", shell=True)
out = subprocess.call("cd ..", shell=True)
使⽤了shell=True这个参数。
这个时候,我们使⽤⼀整个字符串,⽽不是⼀个表来运⾏⼦进程。
Python将先运⾏⼀个shell,再⽤这个shell来解释这整个字符串。
shell命令中有⼀些是shell的内建命令,这些命令必须通过shell运⾏,$cd。
shell=True允许我们运⾏这样⼀些命令。
2. subprocess.check_call
语法:
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False)语义:
运⾏由args指定的命令,直到命令执⾏完成。
如果返回码为零,则返回。否则,抛出 CalledProcessError异常。
CalledProcessError对象包含有返回码的属性值。
上⾯显⽰的参数仅仅是最常见的,下⾯是⽤户更常⽤的参数。
⽰例代码如下:
>>>
>>> subprocess.check_call(["ls", "-l"])
>>> subprocess.check_call("exit 1", shell=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1这个函数在python 2.5版本中引⼊。
WARNING: 使⽤ shell=True 是⼀种安全机制。
NOTE: 不要在这个函数中使⽤ stdout=PIPE 或 stderr=PIPE, 否则会造成⼦进程死锁。
如果需要使⽤管道,可以在 communicate()⽅法中使⽤Popen.
3. subprocess.check_output
语法:
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)语义:
调用子程序的例子运⾏args定义的命令,并返回⼀个字符串表⽰的输出值。
如果返回码为⾮零,则抛出 CalledProcessError异常。
⽰例代码:
>>>
>>> subprocess.check_output(["echo", "Hello World!"])
'Hello World!\n'
>>> subprocess.check_output("exit 1", shell=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
如果要捕捉结果中的标准错误,使⽤ stderr=subprocess.STDOUT参数:
>>>
>>> subprocess.check_output(
... "ls non_existent_file; exit 0",
... stderr=subprocess.STDOUT,
... shell=True)
'ls: non_existent_file: No such file or directory\n'
这个函数在python 2.7版本中引⼊。
WARNING: 使⽤ shell=True 是⼀种安全机制。
NOTE: 不要在这个函数中使⽤ stdout=PIPE 或 stderr=PIPE, 否则会造成⼦进程死锁。
如果需要使⽤管道,可以在 communicate()⽅法中使⽤Popen.
4. subprocess.PIPE
使⽤Popen时,⽤于 stdin, stdout和stderr参数的特殊值,表⽰打开连接标准流的管道。
5. subprocess.STDOUT
使⽤Popen时,⽤于 stderr 参数的特殊值,表⽰将标准错误重定向到标准输出的同⼀个句柄。
6. 异常 subprocess.CalledProcessError
当由 check_call()或 check_output()运⾏的进程返回⾮零状态值时抛出的异常。
7. returncode
⼦进程的退出状态。
8. cmd
⼦进程执⾏的命令。
9. output
如果check_output()抛出异常时,⼦进程的输出值。
否则,没有这个值。
1.1.1. 常⽤的参数
为了⽀持各种⽤户使⽤情况 ,Popen构建函数接收多种可选参数。
对于最典型的情况,许多参数都保留有安全的默认值,这些最常⽤的⽅式如下:
1. args
所有的函数都需要这个参数,并且它是⼀个字符串,或者是程序的参数序列。
提供⼀个参数序列是更推荐的⽅式,因为这样能允许模块接收空格 或 引号中的参数。
如果传递的是单个字符串,要么 shell=True, 或都要么 字符串就程序名字,并且不能带参数。
2. stdin, stdout 和 stderr
stdin, stdout和stderr指定了执⾏程序的标准输⼊,标准输出和标准错误的⽂件句柄。
它们的值可以是PIPE, ⼀个存在的⽂件描述符(正整数),⼀个存在的⽂件对象,或 None.
PIPE 表⽰创建⼀个连接⼦进程的新管道。
默认值 为 None, 表⽰不做重定向。
⼦进程的⽂件句柄可以从⽗进程中继承得到。
另外,stderr可以设置值为 STDOUT,表⽰⼦进程的错误数据可以和标准输出是同⼀个⽂件句柄。
当stdout 或 stderr的值为管道 并且 universal_newlines的值为真时,
对于以 ‘U'模式参数打开的新⾏,所有⾏的结束都会转换成'\n'。
3. shell
如果 shell的值为 True, 则指定的命令⾏会通过shell来执⾏。
如果你使⽤Python来作为流程控制,那这样的设置会很有⽤,因为它提供了绝⼤多数的系统shell命令且可以很⽅便地使⽤shell的各种功能,如 shell 管道,⽂件名通配符,环境变量扩展,以及⽤户⽬录扩展符 ~。
但是,需要注意的是,Python 提供了类似shell功能的实现。
WARNING: 执⾏不受信任来源的shell命令会是⼀个严重的安全问题。
基于这⼀点,shell=True 是不建议的。
⽰例代码如下:
>>>
>>> from subprocess import call
>>> filename = input("What file would you like to display?\n")
What file would you like to display?
non_existent; rm -rf / #
>>> call("cat " + filename, shell=True) # Uh-oh. This will
shell=False 关闭了shell的所有基本功能 ,从⽽不会有上⾯所说的安全漏洞。
可以在Popen构建函数的帮助⽂档中看到,它只有在 shell=False时才能⼯作。
当使⽤ shell=True时,pipes.quote()可以被⽤于转译空格,shell的字符等。
1.1.
2. Popen构建函数
subprocess中更底层的进程创建和管理可以通过Popen类实现。
它提供了更多的灵活性,程序员通过它能处理更多复杂的情况。
语法:
class subprocess.Popen(args, bufsize=0, executable=None,
stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None,
universal_newlines=False, startupinfo=None, creationflags=0)
语义:
在新进程中执⾏⼀个⼦程序。
在Unix中,这个类使⽤ 类似于 os.execvp()⽅式来执⾏⼦程序。
在Windows中,这个类使⽤Windows的 CreateProcess()函数来执⾏⼦程序。
参数解析:
args: ⼀个程序参数序列,或者单个字符串。
默认的,要执⾏的程序应该是序列的第⼀个字段。
如果单个字符串,它的解析依赖于平台
在Unix中,如果 args是⼀个字符串,那么这个字符串解释成被执⾏程序的名字或路径。
然⽽,这种情况只能⽤在不需要参数的程序。
NOTE: 当对args确定了正确的分隔符后,shlex.split()就很有⽤,特别是在复杂的情况下:>>>
>>> import shlex, subprocess
>>> command_line = raw_input()
/bin/vikings - -output "" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)
>>> print args
['/bin/vikings', '-input', '', '-output', '', '-cmd', "echo '$MONEY'"] >>> p = subprocess.Popen(args) # Success!
NOTE: 选项(如 -input) 和 参数(如 ) 在shell中是⽤空格分隔成分离的列表元素。
如果参数需要引号或反斜线,则它们会是⼀个单⼀列表元素。
shell参数(默认值为False)声明了是否使⽤shell来执⾏程序。
如果 shell=True, 它将args看作是⼀个字符串,⽽不是⼀个序列。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论