2019独角兽企业重金招聘Python工程师标准>>>

python子进程模块subprocess

目录

  • 一、subprocess 模块简介

    • 1.1. 使用 subprocess模块
    • 1.1.1. 常用的参数
    • 1.1.2. Popen构建函数
    • 1.1.3.异常
    • 1.1.4. 安全

subprocess--子进程管理器

Top

一、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"])
0
>>> 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"])
0
>>> 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 end badly...

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 -input eggs.txt -output "spam spam.txt" -cmd "echo 'MONEY′">>>args=shlex.split(commandline)>>>printargs[′/bin/vikings′,′−input′,′eggs.txt′,′−output′,′spamspam.txt′,′−cmd′,"echo′MONEY′">>>args=shlex.split(commandline)>>>printargs[′/bin/vikings′,′−input′,′eggs.txt′,′−output′,′spamspam.txt′,′−cmd′,"echo′MONEY'"]
>>> p = subprocess.Popen(args) # Success!

NOTE: 选项(如 -input) 和 参数(如 eggs.txt) 在shell中是用空格分隔成分离的列表元素。
      如果参数需要引号或反斜线,则它们会是一个单一列表元素。
shell参数(默认值为False)声明了是否使用shell来执行程序。
如果 shell=True, 它将args看作是一个字符串,而不是一个序列。

在Unix系统,且 shell=True时,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, 则在子进程被执行前,除0,1和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"], stdout=subprocess.PIPE)
    child2 = subprocess.Popen(["wc"], stdin=child1.stdout,stdout=subprocess.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"], stdin=subprocess.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.

转载于:https://my.oschina.net/u/3754919/blog/1789405

python子进程模块subprocess相关推荐

  1. python 多进程 调用模块内函数_python子进程模块subprocess详解与应用实例 之一

    分类: Python/Ruby 2014-09-09 10:59:42 subprocess--子进程管理器 一.subprocess 模块简介 subprocess最早是在2.4版本中引入的. su ...

  2. python子进程异常结束_Python子进程

    python子进程异常结束 Python subprocess module provides easy functions that allow us to spawn a new process ...

  3. python打印字节流_Python 调用系统命令的模块 Subprocess

    有些时候需要调用系统内部的一些命令,或者给某个应用命令传不定参数时可以使用该模块. 初识 Subprocess 模块 Subprocess 模块提供了多个方法来运行额外的进程.在 Python2.7 ...

  4. Python基础篇【第6篇】: Python模块subprocess

    Python中可以执行shell命令的相关模块和函数有: os.system os.spawn* os.popen*          --废弃 popen2.*           --废弃 com ...

  5. python commands模块在python3.x被subprocess取代

    subprocess 可以执行shell命令的相关模块和函数有: os.system os.spawn os.popen --废弃 popen2.* --废弃 commands.* --废弃,3.x中 ...

  6. python内存分配失败_关于python:如何避免[Errno 12]无法分配使用子进程模块导致的内存错误...

    完整的工作测试案例 当然,根据您在本地和远程计算机上的内存,您的阵列大小会有所不同. z1 = numpy.random.rand(300000000,2); for i in range(1000) ...

  7. python模块--subprocess

    subprocess模块                                                                                         ...

  8. python常用模块-调用系统命令模块(subprocess)

    python常用模块-调用系统命令模块(subprocess) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. subproces基本上就是为了取代os.system和os.spaw ...

  9. Python模块subprocess小记

    在熟悉了Qt的QProcess以后,再回头来看python的subprocess总算不觉得像以前那么恐怖了. 和QProcess一样,subprocess的目标是启动一个新的进程并与之进行通讯. su ...

最新文章

  1. json execel xml 互转
  2. java注解,通过反射解析注解,模仿hibernate,获取sql语句。
  3. Linux 下的五种 IO 模型
  4. 开机报警disk boot sector is to be modified
  5. 2.8加密工具与散列
  6. VI.Multidocument Transactions
  7. 申作军海通机器人_青岛海通机器人系统有限公司
  8. 【读书笔记《Android游戏编程之从零开始》】13.游戏开发基础(Paint 画笔)
  9. 通用版工业制程SPC管理系统,源代码分享
  10. SQL Server2005+SQL Server2000下载
  11. 南京邮电大学网络信息安全——软件漏洞分析与防范(实验一——栈溢出和gs保护机制)
  12. autocad 二次开发 拆分图纸_2,手动创建CAD二次开发项目--AutoCAD二次开发(2020版)...
  13. Unity Graph View打造图形化对话编辑系统(三)
  14. vue中如何引入公共样式的的styl文件
  15. 机器学习梯度消失,梯度爆炸原因
  16. 拒绝纷繁复杂 快速制表软件分享
  17. 微信h5获取用户地址信息
  18. java 地铁费_Java练习题_Map集合,遍历车站编号及名称、计算地铁票价。
  19. NOI 3255:十进制到六进制
  20. 内存溢出问题核查与定位

热门文章

  1. (转)RemoteView 设置控件属性
  2. 2021-11-14Collection
  3. 转载:矩阵的掩膜操作实现图像对比度调整
  4. 计算机网络实验二:应用层和传输层网络协议分析
  5. 机器人学习--有参考意义的视频
  6. 机器人学习--定位、建图和导航问题从古至今
  7. 计算机视觉与深度学习 | 深度学习与VO、SLAM、三维重建【论文及代码篇】
  8. 人工智能 | 自动驾驶与人工智能前沿研究报告(概念篇)
  9. linux安装创建逻辑卷,Linux系统LVM逻辑卷的创建与扩容(命令详解,图文并茂)...
  10. 简析.NET Core 以及与 .NET Framework的关系