学习使用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注意事项的更多相关文章

  1. python的subprocess的简单使用和注意事项

    subprocess是python在2.4引入的模块, 主要用来替代下面几个模块和方法: os.systemos.spawn*os.popen*popen2.*commands.* 可以参考PEP32 ...

  2. python的subprocess:子程序调用(调用执行其他命令);获取子程序脚本当前路径问题

    python当前进程可以调用子进程,子进程可以执行其他命令,如shell,python,java,c... 而调用子进程方法有 os模块 参见:http://blog.csdn.net/longshe ...

  3. jQuery UI resizable使用注意事项、实时等比例拉伸及你不知道的技巧

    这篇文章总结的是我在使用resizable插件的过程中,遇到的问题及变通应用的奇思妙想. 一.resizable使用注意事项 以下是我在jsfiddle上写的测试demo:http://jsfiddl ...

  4. Windows Server 2012 NIC Teaming介绍及注意事项

    Windows Server 2012 NIC Teaming介绍及注意事项 转载自:http://www.it165.net/os/html/201303/4799.html Windows Ser ...

  5. TODO:Golang指针使用注意事项

    TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...

  6. app开发外包注意事项,2017最新资讯

    我们见过很多创业者,栽在这app外包上.很多创业者对于app外包这件事情不是特别重视,以为将事情交给app外包公司就完事了,实际上不是的.无论是从选择app外包公司还是签订合同.售后维护等各方面都有许 ...

  7. favicon.ioc使用以及注意事项

    1.效果 2.使用引入方法 2.1 注意事项:(把图标命名为favicon.ico,并且放在根目录下,同时使用Link标签,多重保险) 浏览器默认使用根目录下的favicon.ico 图标(如果你并没 ...

  8. ORACLE分区表梳理系列(二)- 分区表日常维护及注意事项(红字需要留意)

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  9. 【原】Masonry+UIScrollView的使用注意事项

    [原]Masonry+UIScrollView的使用注意事项 本文转载请注明出处 —— polobymulberry-博客园 1.问题描述 我想实现的使用在一个UIScrollView依次添加三个UI ...

随机推荐

  1. SM2

    一.介绍 #百度 二.生成密钥对及证书 1.使用gmssl工具 详见gmssl 2.go 版本 详见https://github.com/tjfoc/gmsm 3.java版本 #尚未实现 1.初步使 ...

  2. 关于jsonp知识的理解

    jsonp 之前知道是用来解决ajax跨域的问题,但是其本质的原理,还是不清楚. 所以看了一下. js的script 的src里面的连接是可以跨域的,所以可以通过她来实现跨域资源获取. 但是也需要后端 ...

  3. poj 3311(状态压缩DP)

    poj  3311(状态压缩DP) 题意:一个人送披萨从原点出发,每次不超过10个地方,每个地方可以重复走,给出这些地方之间的时间,求送完披萨回到原点的最小时间. 解析:类似TSP问题,但是每个点可以 ...

  4. [OS] 内核态和用户态的区别

    http://blog.csdn.net/fatsandwich/article/details/2131707# http://jakielong.iteye.com/blog/771663 当一个 ...

  5. 一个不错的微信应用JS API库

    1.API能实现什么? 1.分享到微信朋友圈 2.分享给微信好友 3.分享到腾讯微博 4.新的分享接口,包含朋友圈.好友.微博的分享(for iOS) 5.隐藏/显示右上角的菜单入口 6.隐藏/显示底 ...

  6. UVALive6443_Alien Abduction Again

    题意为给你若干个三次函数,以及每一个函数所分布的区间,由于每个函数的所有的系数都是整数,所以最后的函数在整数点处的值也是整数. 现在每次可以插入函数或者询问区间,现在要求每次询问区间后,所有的函数在这 ...

  7. YARN的重启动问题:RM Restart/RM HA/Timeline Server/NM Restart

    ResourceManger Restart ResourceManager负责资源管理和应用的调度,是YARN的核心组件,有可能存在单点失败的问题.ResourceManager Restart是使 ...

  8. enginefuncs_t 结构体中的函数

    就是常见的 g_engfuncs 中的函数.AMXX 里就是 fakemeta 的 EngFunc_** // 这些函数由引擎提供给EXTDLL使用.mp.dll hl.dll ... typedef ...

  9. DAY7-Python学习笔记

    前记: 这几天在弄小程序,view页面的开发很简单,但是在加载图片上遇到了问题,小程序的大小不能超过2M,所以大部分的图片内容要通过request请求服务器来获取,这里之前学习小程序的时候是通过网站A ...

  10. 018 final 关键字的用途

    final关键字的含义 final在Java中是一个保留的关键字,可以声明成员变量.方法.类以及本地变量.一旦你将引用声明作final,你将不能改变这个引用了,编译器会检查代码,如果你试图将变量再次初 ...