使用subprocess.Poen注意事项
学习使用python已经有四个月了,subprocess这个执行linux中shell命令的函数已经用过无数次了,踩到的坑也有几个,写出来分享一下,欢迎大家拍砖头。
1.shell命令中若有管道,一定要多次调用Poen,p1的输出当作p2的输入。
例如:shell命令
hdfs dfs -cat test.log.lzo | lzop -d | head -n 2
此命令可以查看hdfs上面一个lzo文件中的前两行,开始没有看subprocess的手册,直接代码就写成:
shell_comm="hdfs dfs -cat test.log.lzo | lzop -d | head -n 2"
outPipe=subprocess.Popen(shell_comm,shell=True,stdout=subprocess.PIPE)
结果输出那是一堆乱码,纠结了半天,一直以为是编码不统一的问题,找了N久,郁闷良久,最后老大跟我说,subprocess不是这样用的,管道必须使用多个popen,代码改成:
comm1="hdfs dfs -cat test.log.lzo"
comm2="lzop -d"
comm3="head -n 2"
p1=subprocess.Popen(comm1,shell=True,stdout=subprocess.PIPE)
p2=subprocess.Popen(comm2,shell=True,stdoin=p1.stdout,stdout=subprocess.PIPE)
p3=subprocess.Popen(comm3,shell=True,stdoin=p2.stdout,stdout=subprocess.PIPE)
最后p3的输出就是你想要的结果了
2.python2.7多个管道连接输出会出现Broken pipe提示。
像上面代码中多个管道连续输出,最后p3却只取前2行,comm1|2在一直不停的执行,comm3却终止了,此时就会出现Broken pipe提示,这是python的一个bug,具体原因和解决办法可见http://bugs.python.org/issue1652 https://code.google.com/p/python-subprocess32/
3.subprocess一定要收集子进程状态
这就牵扯到我写代码过程中跳的一个坑,看网上写的使用subprocess的例子,都是直接执行命令,然后读取PIPE内容,我也照做,根本没有想到收集什么进程状态这回事。有一天,老大把我叫过去,看着我说:“我发现一个问题,为什么每次你写的这个程序运行起来,服务器内存使用量一下子就上升了2、3十G?”
经过各种traceback和lsof查看进程状态,发现罪魁祸首居然是subprocess,最重要的是我调用了subprocess.Popen之后没有收集子进程状态。我的整个程序运行了5、6分钟,打开了hdfs上的上百个文件,而且都是取开头两行,开启了N个子进程,都没有收集,那么这些子进程的数据全部都算在了程序主进程中,一直占用服务器内存,并且越堆积越多。最后加上状态收集语句之后问题解决。
4.subprocess.wait()与subprocess.communicate()使用问题
subprocess就是开启一个子进程,自己去执行命令,这个子进程的状态肯定得收集,这时候就需要调用wait或者communicate了,手册上面也注明了这两个方法的特点:在数据超过PIPE的缓存时,wait会阻塞进程;communicate会把所有的数据都读取到内存中。
wait:
Warning
This will deadlock if the child process generates enough output to a stdout or stderr pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use communicate() to avoid that.
communicate:
Note
The data read is buffered in memory, so do not use this method if the data size is large or unlimited
那么现在就有一个问题了,当我shell命令执行的结果很大时,我是该用wait还是communicate?用wait直接就阻塞了,肯定不行,用communicate也不行,如果很大的文件,数据都保存在内存,主机直接就卡死了。
解决办法:数据一行一行读取,读取完之后wait,这样既保证了不会阻塞(PIPE中数据有进有出,最后空了才wait),又保证了不会占用大量主机内存(在内存中的数据只有一行line)。
p1=subprocess.Popen(comm1,shell=True,stdout=subprocess.PIPE)
for line in p1.stdout:
pass
p1.wait()
使用subprocess.Poen注意事项的更多相关文章
- python的subprocess的简单使用和注意事项
subprocess是python在2.4引入的模块, 主要用来替代下面几个模块和方法: os.systemos.spawn*os.popen*popen2.*commands.* 可以参考PEP32 ...
- python的subprocess:子程序调用(调用执行其他命令);获取子程序脚本当前路径问题
python当前进程可以调用子进程,子进程可以执行其他命令,如shell,python,java,c... 而调用子进程方法有 os模块 参见:http://blog.csdn.net/longshe ...
- jQuery UI resizable使用注意事项、实时等比例拉伸及你不知道的技巧
这篇文章总结的是我在使用resizable插件的过程中,遇到的问题及变通应用的奇思妙想. 一.resizable使用注意事项 以下是我在jsfiddle上写的测试demo:http://jsfiddl ...
- Windows Server 2012 NIC Teaming介绍及注意事项
Windows Server 2012 NIC Teaming介绍及注意事项 转载自:http://www.it165.net/os/html/201303/4799.html Windows Ser ...
- TODO:Golang指针使用注意事项
TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...
- app开发外包注意事项,2017最新资讯
我们见过很多创业者,栽在这app外包上.很多创业者对于app外包这件事情不是特别重视,以为将事情交给app外包公司就完事了,实际上不是的.无论是从选择app外包公司还是签订合同.售后维护等各方面都有许 ...
- favicon.ioc使用以及注意事项
1.效果 2.使用引入方法 2.1 注意事项:(把图标命名为favicon.ico,并且放在根目录下,同时使用Link标签,多重保险) 浏览器默认使用根目录下的favicon.ico 图标(如果你并没 ...
- ORACLE分区表梳理系列(二)- 分区表日常维护及注意事项(红字需要留意)
版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...
- 【原】Masonry+UIScrollView的使用注意事项
[原]Masonry+UIScrollView的使用注意事项 本文转载请注明出处 —— polobymulberry-博客园 1.问题描述 我想实现的使用在一个UIScrollView依次添加三个UI ...
随机推荐
- Matlab图像匹配问题
已知一个任意形状,查找在大图像中最接近的形状位置. 输入:一个小图形状和一张大图 输出:最接近的形状在大图中的位置 假设: (1)已知形状与目标形状有一定的形变. (2)形状与大图像均为二值图像,图中 ...
- C/C++ 打印文件名、行号、函数名的方法
转自:http://zhidao.baidu.com/link?url=JLCaxBAXLJVcx_8jsyJVF92E_bZjo4ONJ5Ab-HGlNBc1dfzcAyFAIygwP1qr18aa ...
- contos7忘记root密码怎么办
首先在这个界面按"e"键 然后呢就会进入到如下图所示的界面,在LANG=zh_CN.UTF8的后面加上 init=/bin/sh, 再按 [ Ctrl + X ] 进入'单用户模式 ...
- PHP ini_set
PHP ini_set用来设置php.ini的值,在函数执行的时候生效,对于虚拟空间来说,很方便,下面为大家介绍下此方法的使用 PHP ini_set用来设置php.ini的值,在函数执行的时候生 ...
- Dubbo学习(六) dubbo 架构图 以及调用过程
一.Dubbo结构图 duubo结构图 我们解释以下这个架构图:Consumer服务消费者,Provider服务提供者.Container服务容器.消费当然是invoke提供者了,invoke这条 ...
- python自动化之读写
############################################################################# #############在Windows上 ...
- 【uoj#315/bzoj4943】[NOI2017]蚯蚓排队 Hash
题目描述 给出 $n$ 个字符,初始每个字符单独成字符串.支持 $m$ 次操作,每次为一下三种之一: $1\ i\ j$ :将以 $i$ 结尾的串和以 $j$ 开头的串连到一起. $2\ i$ :将 ...
- 环形buffer缓冲区
#include <stdio.h> #include <string.h> #include <malloc.h> struct CircleBuf { char ...
- MySQL 大表备份、改表
0.背景: 需要对一个千万行数据的表新增字段,具体操作: a.dump 数据 b.delete 数据 c.alter 表 MySQL 版本为5.5,alter表时MySQL会锁表:表行数虽多,当数据 ...
- Day24--Part2-伪Ajax(iframe)
参考:http://www.pythonsite.com/ 赵凡同学的博客,每一份努力都值得期许! 867468837 Ajax操作---伪Ajax (iframe) 一,基于iframe实现伪Aja ...