网站界面设计和ios移动界面设计的区别,深圳专业建站公司有哪些,商城网站建设二次开发,做外贸soho网站的公司吗分类#xff1a; Python/Ruby
2014-09-09 10:59:42
subprocess--子进程管理器
一、subprocess 模块简介
subprocess最早是在2.4版本中引入的。
subprocess模块用来生成子进程#xff0c;并可以通过管道连接它们的输入/输出/错误#xff0c;以及获得它们的返回值。
它用来代替…分类 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, *, stdinNone, stdoutNone, stderrNone, shellFalse)
语义:
运行由args指定的命令直到命令结束后返回 返回码的属性值。
上面的参数是最常见的方式下面是示例代码:subprocess.call([ls, -l])
0subprocess.call(exit 1, shellTrue)
1
WARNING: 使用 shellTrue 是一种安全保护机制。
NOTE: 在使用这个函数时不要使用 stdoutPIPE 或 stderrPIPE 参数
不然会导致子进程输出的死锁。
如果要使用管道可以在 communicate()方法中使用Popen
示例代码:
import subprocess
rc subprocess.call([ls,-l])
可以通过一个shell来解释一整个字符串:
import subprocess
out subprocess.call(ls -l, shellTrue)
out subprocess.call(cd .., shellTrue)
使用了shellTrue这个参数。
这个时候我们使用一整个字符串而不是一个表来运行子进程。
Python将先运行一个shell再用这个shell来解释这整个字符串。
shell命令中有一些是shell的内建命令这些命令必须通过shell运行$cd。
shellTrue允许我们运行这样一些命令。
2. subprocess.check_call
语法:
subprocess.check_call(args, *, stdinNone, stdoutNone, stderrNone, shellFalse)
语义:
运行由args指定的命令直到命令执行完成。
如果返回码为零则返回。否则抛出 CalledProcessError异常。
CalledProcessError对象包含有返回码的属性值。
上面显示的参数仅仅是最常见的下面是用户更常用的参数。
示例代码如下:subprocess.check_call([ls, -l])
0subprocess.check_call(exit 1, shellTrue)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command exit 1 returned non-zero exit status 1
这个函数在python 2.5版本中引入。
WARNING: 使用 shellTrue 是一种安全机制。
NOTE: 不要在这个函数中使用 stdoutPIPE 或 stderrPIPE, 否则会造成子进程死锁。
如果需要使用管道可以在 communicate()方法中使用Popen.
3. subprocess.check_output
语法:
subprocess.check_output(args, *, stdinNone, stderrNone, shellFalse, universal_newlinesFalse)
语义:
运行args定义的命令并返回一个字符串表示的输出值。
如果返回码为非零则抛出 CalledProcessError异常。
示例代码:subprocess.check_output([echo, Hello World!])
Hello World!\nsubprocess.check_output(exit 1, shellTrue)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command exit 1 returned non-zero exit status 1
如果要捕捉结果中的标准错误使用 stderrsubprocess.STDOUT参数:subprocess.check_output(
... ls non_existent_file; exit 0,
... stderrsubprocess.STDOUT,
... shellTrue)
ls: non_existent_file: No such file or directory\n
这个函数在python 2.7版本中引入。
WARNING: 使用 shellTrue 是一种安全机制。
NOTE: 不要在这个函数中使用 stdoutPIPE 或 stderrPIPE, 否则会造成子进程死锁。
如果需要使用管道可以在 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
所有的函数都需要这个参数并且它是一个字符串或者是程序的参数序列。
提供一个参数序列是更推荐的方式因为这样能允许模块接收空格 或 引号中的参数。
如果传递的是单个字符串要么 shellTrue, 或都要么 字符串就程序名字并且不能带参数。
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命令会是一个严重的安全问题。
基于这一点shellTrue 是不建议的。
示例代码如下:from subprocess import callfilename input(What file would you like to display?\n)
What file would you like to display?
non_existent; rm -rf / #call(cat filename, shellTrue) # Uh-oh. This will end badly...
shellFalse 关闭了shell的所有基本功能 从而不会有上面所说的安全漏洞。
可以在Popen构建函数的帮助文档中看到它只有在 shellFalse时才能工作。
当使用 shellTrue时pipes.quote()可以被用于转译空格shell的字符等。
1.1.2. Popen构建函数
subprocess中更底层的进程创建和管理可以通过Popen类实现。
它提供了更多的灵活性程序员通过它能处理更多复杂的情况。
语法:
class subprocess.Popen(args, bufsize0, executableNone,
stdinNone, stdoutNone, stderrNone,
preexec_fnNone, close_fdsFalse, shellFalse, cwdNone, envNone,
universal_newlinesFalse, startupinfoNone, creationflags0)
语义:
在新进程中执行一个子程序。
在Unix中这个类使用 类似于 os.execvp()方式来执行子程序。
在Windows中这个类使用Windows的 CreateProcess()函数来执行子程序。
参数解析:
args: 一个程序参数序列或者单个字符串。
默认的要执行的程序应该是序列的第一个字段。
如果单个字符串它的解析依赖于平台
在Unix中如果 args是一个字符串那么这个字符串解释成被执行程序的名字或路径。
然而这种情况只能用在不需要参数的程序。
NOTE: 当对args确定了正确的分隔符后shlex.split()就很有用特别是在复杂的情况下import shlex, subprocesscommand_line raw_input()
/bin/vikings -input eggs.txt -output spam spam.txt -cmd echo $MONEYargs shlex.split(command_line)print args
[/bin/vikings, -input, eggs.txt, -output, spam spam.txt, -cmd, echo $MONEY]p subprocess.Popen(args) # Success!
NOTE: 选项(如 -input) 和 参数(如 eggs.txt) 在shell中是用空格分隔成分离的列表元素。
如果参数需要引号或反斜线则它们会是一个单一列表元素。
shell参数(默认值为False)声明了是否使用shell来执行程序。
如果 shellTrue, 它将args看作是一个字符串而不是一个序列。
在Unix系统且 shellTrue时shell默认使用 /bin/sh.
如果 args是一个字符串则它声明了通过shell执行的命令。这意味着字符串必须要使用正确的格式。
如果 args是一个序列则第一个元素就是命令字符串而其它的元素都作为参数使用。
可以这样说Popen等价于:
Popen([/bin/sh, -c, args[0], args[1], ...])
bufsize: 如果指定了值则它和内建函数 open()对应的参数有相同的意义:
0 -- 表示不缓冲
1 -- 表示缓冲
任何其它的正数值表示buffer的大小。
负数值表示使用系统默认值通常表示完全缓冲。
它的默认值为零。
NOTE: 如果遇到性能问题建议将bufsize设置成 -1 或足够大的正数(如 4096。
executable: 指定了用于代替执行的程序。它极少会用到。
stdin, stdout, stderr指定了执行程序的标准输入标准输出和标准错误的文件句柄。
有效的值可以是 PIPE, 一个存在的文件描述符或存在的文件对象或 None.
默认值为 None。
stderr可以设置成STDOUT, 它表示将子进程的stderr数据重定向到stdout.
preexec_fn: 如果它被设置成可调用对象那么这个对象会在子进程执行前被子进程调用只用于Unix.
close_fds: 如果设置为True 则在子进程被执行前除01和2之外的所有文件描述符都将被关闭只用于Unix。
cwd: 当它不为 None时子程序在执行前它的当前路径会被替换成 cwd的值。
这个路径并不会被添加到可执行程序的搜索路径所以cwd不能是相对路径。
env: 当它不为 None时它是新进程的环境变量的映射。
可以用它来代替当前进程的环境。
universal_newlines: 为真时文件对象 stdout和 stderr都被以文本文件的方式打开
示例代码:
1. Popen对象创建后主程序不会自动等待子进程完成。
我们必须调用对象的wait()方法父进程才会等待 (也就是阻塞block)
import subprocess
child subprocess.Popen([ping,-c,5,www.google.com])
print(parent process)
从运行结果中看到父进程在开启子进程之后并没有等待child的完成而是直接运行print。
2. 对比等待的情况:
import subprocess
child subprocess.Popen([ping,-c,5,www.google.com])
child.wait()
print(parent process)
此外你还可以在父进程中对子进程进行其它操作比如我们上面例子中的child对象:
child.poll() # 检查子进程状态
child.kill() # 终止子进程
child.send_signal() # 向子进程发送信号
child.terminate() # 终止子进程
子进程的PID存储在child.pid
3. 可以在Popen()建立子进程的时候改变标准输入、标准输出和标准错误
并可以利用subprocess.PIPE将多个子进程的输入和输出连接在一起构成管道(pipe):
import subprocess
child1 subprocess.Popen([ls,-l], stdoutsubprocess.PIPE)
child2 subprocess.Popen([wc], stdinchild1.stdout,stdoutsubprocess.PIPE)
out child2.communicate()
print(out)
subprocess.PIPE实际上为文本流提供一个缓存区。
child1的stdout将文本输出到缓存区随后child2的stdin从该PIPE中将文本读取走。
child2的输出文本也被存放在PIPE中直到communicate()方法从PIPE中读取出PIPE中的文本。
要注意的是communicate()是Popen对象的一个方法该方法会阻塞父进程直到子进程完成。
4. 还可以利用communicate()方法来使用PIPE给子进程输入:
import subprocess
child subprocess.Popen([cat], stdinsubprocess.PIPE)
child.communicate(vamei)
我们启动子进程之后cat会等待输入直到我们用communicate()输入vamei。
通过使用subprocess包我们可以运行外部程序。这极大的拓展了Python的功能。
如果你已经了解了操作系统的某些应用你可以从Python中直接调用该应用(而不是完全依赖Python)
并将应用的结果输出给Python并让Python继续处理。
shell的功能(比如利用文本流连接各个应用)就可以在Python中实现。
1.1.3.异常
在开始执行新程序之前子进程抛出的异常会被重新抛出到父进程。
另外异常对象会有一个额外的属性叫做 child_traceback, 它是一个字符串包含从子程序的观察点追踪到的信息。
最常见的抛出的异常是 OSError 当它发生时通常是我们执行了一个不存在的文件。应用程序应当要能处理这个异常。
如果使用无效的参数调用 Popen会抛出 ValueError异常。
如果被调用进程的返回码不为零则check_call()和check_output()会抛出 CalledProcessError异常。
1.1.4. 安全
Unlike some other popen functions, this implementation will never call a system shell implicitly.
This means that all characters, including shell metacharacters, can safely be passed to child processes.
Obviously, if the shell is invoked explicitly, then it is the application’s responsibility to ensure that
all whitespace and metacharacters are quoted appropriately.
阅读(56696) | 评论(0) | 转发(3) |
给主人留下些什么吧~~
评论热议
请登录后评论。