欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python关于使用subprocess.Popen时遇到的一个小问题记录

程序员文章站 2022-07-15 07:59:58
...

python中有很多种方式是可以直接执行系统命令的,类似于os.systemcommands(python3中已经移除)、subprocess等。

其中os.system的返回值只是执行命令的返回状态码,并不会得到命令的执行输出;commands在Windows平台下并不好使;日常中更多的还是使用subprocess

之前只是常规的使用subprocess简单的封装一个方法使用,如下:

# utf-8
"""
python 2.7的执行环境
"""
from subprocess import Popen, PIPE


def getoutput(cmd, cwd=None, env=None):
    p = Popen(cmd, stdout=PIPE, stdin=PIPE, 
              stderr=PIPE, cwd=cwd, env=env, 
              shell=True)
    out, err = p.communicate()
    if err:
        print err
    return p.returncode, out

status, output = getoutput('whoami')
复制代码

多数情况下这个方法运行都是正常的,之前前几天,遇到一个问题。

在Redhat 6.8的虚拟机上通过此方法执行vgsvgs等命令时,会输出大量异常信息

File descriptor 4 (pipe:[526520]) leaked on pvremove invocation. Parent PID 46499:python
File descriptor 5 (pipe:[526520]) leaked on pvremove invocation. Parent PID 46499:python
File descriptor 6 (pipe:[526520]) leaked on pvremove invocation. Parent PID 46499:python
...
复制代码

实际在虚拟机中命令行直接执行lvs是是正常的

[[email protected] test]# lvs
LV          VG        Attr        LSize        Pool        Origin       Data%       Meta%        Move        log         Cpy%Sync  Convert
lvoradata   appvg    -wi-ao----   270.00g
lvu01       appvg    -wi-ao----   30.00g
root        vg00     -wi-ao----   19.53g
[[email protected] test]# echo $?
0
复制代码

命令输出没有问题,执行返回码也是一致的正常,为什么在python执行的时候会有这些异常输出呢?

再次感谢强大的(Google)[www.google.com],在*中的找到了相似问题。 其中第二个回答是想要的结果。

So for lvm commands like pvremove, you can avoid the leak by setting close_fds=True in your subprocess.Popen call.

原来,在系统调用时,lvm必须要标准描述符的stdin stdout stderr才可用,如果是其他的就会被关闭并且抛出如上的提示信息。所以,通过指定close_fds=True继承文件描述符,从而解决这个问题。

from subprocess import Popen, PIPE


def getoutput(cmd, cwd=None, env=None):
    p = Popen(cmd, stdout=PIPE, stdin=PIPE, 
              stderr=PIPE, cwd=cwd, env=env, 
              shell=True, close_fds=True)
    out, err = p.communicate()
    if err:
        print err
    return p.returncode, out
复制代码

在使用subprocess.Popen类时,实际对内部参数并不了解,只知道要这么做,但并不清楚为什么要这么做。在解决以上问题的过程中,才算是看了次subprocess的源码,对其中的一次额参数有了简单的认识。

果然还是要多看源码。

参考

Leak when run subprocess in python

Python subprocess