python的subprocess的简单使用和注意事项
subprocess是python在2.4引入的模块, 主要用来替代下面几个模块和方法:
os.system
os.spawn*
os.popen*
popen2.*
commands.*
可以参考PEP324: http://legacy.python.org/dev/peps/pep-0324/
这是一个用来调用外部命令的模块, 替代了一些旧的模块, 提供了更加友好统一的接口.
三个封装方法
使用下面三个方法的时候, 注意两个问题: 1. shell=True或False, 两种解析方式是不同的 2. 注意PIPE的使用, 可能导致卡死
subprocess.call 运行命令, 等待完成, 并返回returncode
subprocess.check_call 运行命令, 等待完成, 如果返回值为0, 则返回returncode, 否则抛出带有returncode的CalledPorcessError异常.
subprocess.check_output 和check_call类似, 会检查返回值是否为0, 返回stdout.
卡死常见的原因
这个模块在使用的时候, 可能会出现子进程卡死或hang住的情况. 一般出现这种情况的是这样的用法.
import subprocess
import shlex proc = subprocess.Popen(shlex.split(cmd), stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
shell=False, universal_newlines=True)
print proc.stdout.read()
这里的直接读取了Popen对象的stdout, 使用了subprocess.PIPE. 这种情况导致卡死的原因是PIPE管道的缓存被充满了, 无法继续写入, 也没有将缓存中的东西读出来.
官方文档的提示(Popen.wait()方法的Warning)
This will deadlock when using stdout=PIPE and/or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use communicate() to avoid that.
为了解决这个问题, Popen有一个communicate方法, 这个方法会将stdout和stderr数据读入到内存, 并且会一直独到两个流的结尾(EOF). communicate可以传入一个input参数, 用来表示向stdin中写入数据, 可以做到进程间的数据通信.
注意: 官方文档中提示, 读取的数据是缓存在内存中的, 所以当数据量非常大或者是无限制的时候, 不要使用communicate, 应该会导致OOM.
一般情况下, stdout和stderr数据量不是很大的时候, 使用communicate不会导致问题, 量特别大的时候可以考虑使用文件来替代PIPE, 例如stdout=open("stdout", "w")[参考1].
参考2中给出了另一种解决的思路, 使用select来读取Popen的stdout和stderr中的数据, select的这种用法windows下是不支持的, 不过可以做到比较实时的读取数据.
Popen中的shell参数含义
官方文档中推荐shell=False, 这种方式更加安全, 我们来看一下官方给出的例子.
>>> 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...
上面这种命令拼写的方式会导致一个安全问题, 就是用户可以进行类似sql注入的shell注入, 删除整个系统的文件, 这个是极其危险的.
shell=False会屏蔽shell中的很多特性, 所以可以避免上述这种安全问题, 当需要暴露给用户去使用的时候, 尤其要注意上述的安全问题.
shell=True的时候就是按照shell的方式解析和运行的.
Popen的一些简单调优思路
有个bufsize的参数, 这个默认是0, 就是不缓存, 1表示行缓存, 其他正数表示缓存使用的大小, 负数-1表示是使用系统默认的缓存大小.
在运行性能遇到问题时, 可能是缓存区未开启或者太小, 导致了子进程被卡住, 效率低下, 可以考虑配置为-1或4096.
需要实时读取stdout和stderr的, 可以查阅[参考2], 使用select来读取stdout和stderr流.
参考:
- 小心subprocess的PIPE卡住你的python程序: http://noops.me/?p=92
 - pipe large amount of data to stdin while using subprocess.Popen: http://stackoverflow.com/questions/5911362/pipe-large-amount-of-data-to-stdin-while-using-subprocess-popen
 - python docs: http://docs.python.org/2/library/subprocess.html
 
python的subprocess的简单使用和注意事项的更多相关文章
- Python 基于Python及zookeeper实现简单分布式任务调度系统设计思路及核心代码实现
		
基于Python及zookeeper实现简单分布式任务调度系统设计思路及核心代码实现 by:授客 QQ:1033553122 测试环境 功能需求 实现思路 代码实践(关键技术点实现) 代码模块组织 ...
 - python定义的一个简单的shell函数的代码
		
把写代码过程中经常用到的一些代码段做个记录,如下代码段是关于python定义的一个简单的shell函数的代码. pipe = subprocess.Popen(cmd, stdout=subproce ...
 - Python常用的库简单介绍一下
		
Python常用的库简单介绍一下fuzzywuzzy ,字符串模糊匹配. esmre ,正则表达式的加速器. colorama 主要用来给文本添加各种颜色,并且非常简单易用. Prettytable ...
 - Python基础篇【第6篇】: Python模块subprocess
		
subprocess Python中可以执行shell命令的相关模块和函数有: os.system os.spawn* os.popen* --废弃 popen2.* ...
 - python 多线程就这么简单(续)
		
之前讲了多线程的一篇博客,感觉讲的意犹未尽,其实,多线程非常有意思.因为我们在使用电脑的过程中无时无刻都在多进程和多线程.我们可以接着之前的例子继续讲.请先看我的上一篇博客. python 多线程就这 ...
 - 【Python】 Subprocess module
		
1. subprocess.check_output() 2.subprocess.call() 3. subprocess.check_call() the methods 1.2.3 are ar ...
 - Python模块subprocess小记
		
转自:http://www.oschina.net/question/234345_52660 熟悉了Qt的QProcess以后,再回头来看python的subprocess总算不觉得像以前那么恐怖了 ...
 - python模块介绍- HTMLParser 简单的HTML和XHTML解析器
		
python模块介绍- HTMLParser 简单的HTML和XHTML解析器 2013-09-11 磁针石 #承接软件自动化实施与培训等gtalk:ouyangchongwu#gmail.comqq ...
 - 基于Python使用SVM识别简单的字符验证码的完整代码开源分享
		
关键字:Python,SVM,字符验证码,机器学习,验证码识别 1 概述 基于Python使用SVM识别简单的验证字符串的完整代码开源分享. 因为目前有了更厉害的新技术来解决这类问题了,但是本文作 ...
 
随机推荐
- U盘安装Centos7.1操作系统的问题记录
			
需要的软硬件环境>>>>>>>>>>>>>>>>>1.服务器(笔者用的笔记本).U盘2.Cento ...
 - linux上jar包的运行
			
指定目录: #!/bin/bash source /etc/profile log() { echo `date +[%Y-%m-%d" "%H:%M:%S]` $1 } log ...
 - split陷阱
			
如果split最后一个为空,则要这么写 String[] lines=line.split(",",-1);
 - Python重要基础点
			
这里记录一些实际编写代码时遇到的常用/重要的内容,有前辈的,也有自己整理加进来的. 以点的形式记录,之后遇到的内容会慢慢补充进来 1. 斜杠 / :斜字第一笔, 转义用反斜杠 \ : 转的最后一笔 2 ...
 - CTP API 开发之二 :制作CTP java版 API
			
目前上期技术CTP系统提供的API版本是C++版本 SWIG是一个能将C/C++接口转换为其他语言的工具,目前可以支持Python,Java,R等语言. 本文主要介绍Windows 32/64位平台下 ...
 - Oracle卸载之Linux下卸载oracle11g的方法
			
1.使用SQL*PLUS停止数据库 如果不能通过sysdba登陆可以用nolog用户登陆后切换至sysdba [oracle@OracleTest oracle]$ sqlplus /nolog S ...
 - ubuntu x64 debootstrap
			
sudo debootstrap jessie /mnt/jessie http://mirrors.163.com/debian
 - C++中的类成员指针
			
写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...
 - VS 2005 处理条件
			
1. VS 设置断点; 2.VS 查找需要跟踪的内存地址,如果是指针,需要取指针存放地的地址; 3. 4.继续运行,直到内存内容被改写.
 - sql中rownumber()over()的用法
			
语法: ROW_NUMBER ( ) OVER ( [ PARTITION BY value_expression , ... [ n ] ] order_by_clause ) 通过语法可以看出 o ...