zoukankan      html  css  js  c++  java
  • python3之subprocess常见方法使用

    一、常见subprocess方法

    1、subprocess.getstatusoutput(cmd)

    官方解释:

    Return (exitcode, output) of executing cmd in a shell.

    Execute the string 'cmd' in a shell with 'check_output' and
    return a 2-tuple (status, output). The locale encoding is used
    to decode the output and process newlines.

    cmd可以直接执行shell命令,而不需要cmd命令以列表输入----subprocess.getstatusoutput("cat /proc/meminfo")

    返回值包含cmd的执行状态和执行结果,可以直接赋值给某个变量

    实例:

    >>> ret = subprocess.getoutput('ls -l')
    >>> print(ret)
    总用量 160
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
    drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
    drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
    >>> retcode, output = subprocess.getstatusoutput('ls -l')
    >>> print(retcode)
    0
    >>> print(output)
    总用量 160
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
    drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
    drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
    >>> retcode, output = subprocess.getstatusoutput('ls -l /test')
    >>> print(retcode)
    2
    >>> print(output)
    ls: 无法访问/test: 没有那个文件或目录

    2、subprocess.getoutput(cmd)

    官方解释:

    Return output (stdout or stderr) of executing cmd in a shell.

    Like getstatusoutput(), except the exit status is ignored and the return
    value is a string containing the command's output

    cmd可以直接执行shell命令,而不需要cmd命令以列表输入---subprocess.getoutput("cat /proc/meminfo")
    返回值包含cmd的执行结果,可以直接赋值给某个变量
    功能和getstatusoutput类似

    3、subprocess.run(*popenargs, input=None, timeout=None, check=False, **kwargs))

    Run command with arguments and return a CompletedProcess instance.   执行传入命令参数后,返回CompletedProcess实例
    The returned instance will have attributes args, returncode, stdout and
    stderr. By default, stdout and stderr are not captured, and those attributes
    will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them.


    check等于True的时候,当执行状态不是0时,会抛出CalledProcessError异常提示

    传入命令参数时,需要以多个命令拆分按照列表形式传入:subprocess.run(['df', '-h'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)

    如果传入参数同时传入shell=True,则传入一个字符串args,shell命令而不是待执行的shell命令序列

    实例:
    >>> subprocess.run(["ls", "-l"])  # doesn't capture output
    CompletedProcess(args=['ls', '-l'], returncode=0)
    
    >>> subprocess.run("exit 1", shell=True, check=True)
    Traceback (most recent call last):
      ...
    subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
    
    >>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
    CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
    stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null
    ')
    
    
    
     

    4、subprocess.call()

    官方解释:

    Run command with arguments. Wait for command to complete or
    timeout, then return the returncode attribute

     传入shell命令参数格式subprocess.check_call(["ls""-l"])

    如果传入参数同时传入shell=True,则可以传入一个字符串shell命令而不是待执行的shell命令列表--subprocess.check_call("exit 1", shell=True)
    返回参数仅返回执行状态码,可通过把结果复制给某个变量查看,如果直接在linux下python编译器执行该命令会直接显示命令执行的结果

    实例:
    >>> subprocess.call(['ls',  '-l'])
    总用量 160
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
    drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
    drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
    0
    >>> subprocess.call('ls -l', shell=True)
    总用量 160
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
    drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
    drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
    0
    >>> subprocess.call(['ls',  '-l'], stdout=subprocess.DEVNULL)
    0
    >>> subprocess.call(['ls',  '-l', '/test'])
    ls: 无法访问/test: 没有那个文件或目录
    2

    5、subprocess.check_call()

    官方解释:

    Run command with arguments.  Wait for command to complete.  If
    the exit code was zero then return, otherwise raise
    CalledProcessError. The CalledProcessError object will have the
    return code in the returncode attribute.

    check_call基本和call功能一样,只是增加了返回状态码校验,如果执行状态码是0,则返回0,否则抛出异常

    实例:

    >>> subprocess.check_call(['ls',  '-l'])
    总用量 160
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
    drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
    drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
    0
    >>> subprocess.check_call('ls -l', shell=True)
    总用量 160
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
    drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
    drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
    0
    >>> subprocess.check_call('ls -l /test', shell=True)
    ls: 无法访问/test: 没有那个文件或目录
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/lib/python3.4/subprocess.py", line 557, in check_call
        raise CalledProcessError(retcode, cmd)
    subprocess.CalledProcessError: Command 'ls -l /test' returned non-zero exit status 2

    6、subprocess.check_output()

    官方解释:

    Run command with arguments and return its output.

    If the exit code was non-zero it raises a CalledProcessError. The
    CalledProcessError object will have the return code in the returncode
    attribute and output in the output attribute.
    执行命令,如果状态码是0,则返回执行结果,否则抛出异常--
    subprocess.check_output(["ls""-l"])
    如果传入参数同时传入shell=True,则可以传入一个字符串shell命令而不是待执行的shell命令列表--
    subprocess.check_call("exit 1", shell=True)
    返回值包含cmd的执行结果,可以直接赋值给某个变量

    实例:
    >>> ret = subprocess.check_output(['ls',  '-l'])
    >>> print(ret)
    b' xe5x85xacxe5x85xb1xe7x9ax84
    drwxr-xr-x  2 wader wader   4096 12xe6x9cx88  7  2015 xe6xa8xa1xe6x9dxbf
    drwxr-xr-x  2 wader wader   4096 12xe6x9cx88  7  2015 xe8xa7x86xe9xa2x91
    drwxr-xr-x  2 wader wader   4096 12xe6x9cx88  7  2015 xe5x9bxbexe7x89x87
    drwxr-xr-x  2 wader wader   4096 12xe6x9cx88  7  2015 xe6x96x87xe6xa1xa3
    drwxr-xr-x  2 wader wader   4096  4xe6x9cx88 13  2016 xe4xb8x8bxe8xbdxbd
    drwxr-xr-x  2 wader wader   4096 12xe6x9cx88  7  2015 xe9x9fxb3xe4xb9x90
    drwxr-xr-x  7 wader wader   4096  5xe6x9cx88 26  2016 xe6xa1x8cxe9x9dxa2
    '
    >>> ret = subprocess.check_output(['ls',  '-l'], universal_newlines=True)
    >>> print(ret)
    总用量 160
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
    drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
    drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
    drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面

    二、subprocess.Popen()类--用于执行复杂的系统命令

    该类用于在一个新的进程中执行一个子程序。前面我们提到过,上面介绍的这些函数都是基于subprocess.Popen类实现的,通过使用这些被封装后的高级函数可以很方面的完成一些常见的需求。由于subprocess模块底层的进程创建和管理是由Popen类来处理的,因此,当我们无法通过上面哪些高级函数来实现一些不太常见的功能时就可以通过subprocess.Popen类提供的灵活的api来完成。

    1、subprocess.Popen的构造函数

    def __init__(self, args, bufsize=-1, executable=None,
                     stdin=None, stdout=None, stderr=None,
                     preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
                     shell=False, cwd=None, env=None, universal_newlines=False,
                     startupinfo=None, creationflags=0,
                     restore_signals=True, start_new_session=False,
                     pass_fds=(), *, encoding=None, errors=None)

    构造函数详细参数说明和其他实现过程可以参考对应subprocess库文件

    参数说明:

    • args: 要执行的shell命令,可以是字符串,也可以是命令各个参数组成的序列。当该参数的值是一个字符串时,该命令的解释过程是与平台相关的,因此通常建议将args参数作为一个序列传递。
    • bufsize: 指定缓存策略,0表示不缓冲,1表示行缓冲,其他大于1的数字表示缓冲区大小,负数 表示使用系统默认缓冲策略。
    • stdin, stdout, stderr: 分别表示程序标准输入、输出、错误句柄。
    • preexec_fn: 用于指定一个将在子进程运行之前被调用的可执行对象,只在Unix平台下有效。
    • close_fds: 如果该参数的值为True,则除了0,1和2之外的所有文件描述符都将会在子进程执行之前被关闭。
    • shell: 该参数用于标识是否使用shell作为要执行的程序,如果shell值为True,则建议将args参数作为一个字符串传递而不要作为一个序列传递。
    • cwd: 如果该参数值不是None,则该函数将会在执行这个子进程之前改变当前工作目录。
    • env: 用于指定子进程的环境变量,如果env=None,那么子进程的环境变量将从父进程中继承。如果env!=None,它的值必须是一个映射对象。
    • universal_newlines: 如果该参数值为True,则该文件对象的stdin,stdout和stderr将会作为文本流被打开,否则他们将会被作为二进制流被打开。
    • startupinfo和creationflags: 这两个参数只在Windows下有效,它们将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如主窗口的外观,进程优先级等。

    2. subprocess.Popen类的实例可调用的方法

    方法描述
    Popen.poll() 用于检查子进程(命令)是否已经执行结束,没结束返回None,结束后返回状态码。
    Popen.wait(timeout=None) 等待子进程结束,并返回状态码;如果在timeout指定的秒数之后进程还没有结束,将会抛出一个TimeoutExpired异常。
    Popen.communicate(input=None, timeout=None) 该方法可用来与进程进行交互,比如发送数据到stdin,从stdout和stderr读取数据,直到到达文件末尾。
    Popen.send_signal(signal) 发送指定的信号给这个子进程。
    Popen.terminate() 停止该子进程。
    Popen.kill() 杀死该子进程。

    关于communicate()方法的说明:

    • 该方法中的可选参数 input 应该是将被发送给子进程的数据,或者如没有数据发送给子进程,该参数应该是None。input参数的数据类型必须是字节串,如果universal_newlines参数值为True,则input参数的数据类型必须是字符串。
    • 该方法返回一个元组(stdout_data, stderr_data),这些数据将会是字节穿或字符串(如果universal_newlines的值为True)。
    • 如果在timeout指定的秒数后该进程还没有结束,将会抛出一个TimeoutExpired异常。捕获这个异常,然后重新尝试通信不会丢失任何输出的数据。但是超时之后子进程并没有被杀死,为了合理的清除相应的内容,一个好的应用应该手动杀死这个子进程来结束通信。
    • 需要注意的是,这里读取的数据是缓冲在内存中的,所以,如果数据大小非常大或者是无限的,就不应该使用这个方法

    3. subprocess.Popen使用实例

    实例1、

    >>> import subprocess
    >>>
    >>> p = subprocess.Popen('df -Th', stdout=subprocess.PIPE, shell=True)
    >>> print(p.stdout.read())
    Filesystem     Type      Size  Used Avail Use% Mounted on
    /dev/vda1      ext4       40G   12G   26G  31% /
    devtmpfs       devtmpfs  3.9G     0  3.9G   0% /dev
    tmpfs          tmpfs     3.9G     0  3.9G   0% /dev/shm
    tmpfs          tmpfs     3.9G  386M  3.5G  10% /run
    tmpfs          tmpfs     3.9G     0  3.9G   0% /sys/fs/cgroup
    tmpfs          tmpfs     783M     0  783M   0% /run/user/0
    tmpfs          tmpfs     783M     0  783M   0% /run/user/1000

    实例2

    >>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    >>> obj.stdin.write('print(1) 
    ')
    >>> obj.stdin.write('print(2) 
    ')
    >>> obj.stdin.write('print(3) 
    ')
    >>> out,err = obj.communicate()
    >>> print(out)
    1
    2
    3
    
    >>> print(err)

    实例3

    >>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    >>> out,err = obj.communicate(input='print(1) 
    ')
    >>> print(out)
    1
    
    >>> print(err)

    实例4

    实现类似df -Th | grep data命令的功能,实际上就是实现shell中管道的共功能

    >>> 
    >>> p1 = subprocess.Popen(['df', '-Th'], stdout=subprocess.PIPE)
    >>> p2 = subprocess.Popen(['grep', 'data'], stdin=p1.stdout, stdout=subprocess.PIPE)
    >>> out,err = p2.communicate()
    >>> print(out)
    /dev/vdb1      ext4      493G  4.8G  463G   2% /data
    /dev/vdd1      ext4     1008G  420G  537G  44% /data1
    /dev/vde1      ext4      985G  503G  432G  54% /data2
    
    >>> print(err)
    None

    三、总结

    那么我们到底该用哪个模块、哪个函数来执行命令与系统及系统进行交互呢?下面我们来做个总结:

    1、如果你的应用使用的Python 2.4以上,但是是Python 3.5以下的版本,Python官方给出的建议是使用subprocess.call()函数。Python 2.5中新增了一个subprocess.check_call()函数,Python 2.7中新增了一个subprocess.check_output()函数,这两个函数也可以按照需求进行使用

    2、如果你的应用使用的是Python 3.5及以上的版本(目前应该还很少),Python官方给出的建议是尽量使用subprocess.run()函数

    3、当subprocess.call()、subprocess.check_call()、subprocess.check_output()和subprocess.run()这些高级函数无法满足需求时,我们可以使用subprocess.Popen类来实现我们需要的复杂功能

    不过经过个人试验认为getoutput、getstatusoutput方法使用比较便捷,subprocess适合个性化的执行

    参考链接:https://www.cnblogs.com/yyds/p/7288916.html

  • 相关阅读:
    react 采坑记录
    理解JS 模块化
    MongoDB使用教程
    scss
    gulp 使用教程
    node.js 简单入门
    jQuery
    jQuery
    php+mysql+bootstrap 实现成绩管理系统
    SVN的commit功能用bat实现
  • 原文地址:https://www.cnblogs.com/clarenceyang/p/9811785.html
Copyright © 2011-2022 走看看