zoukankan      html  css  js  c++  java
  • subprocess模块

    官方推荐使用
    subprocess.run() 函数
    或者
    subprocess.Peopen()类

    转载自https://www.cnblogs.com/zhou2019/p/10582716.html

    总结

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

    • 首先应该知道的是,Python2.4版本引入了subprocess模块用来替换os.system()、os.popen()、os.spawn*()等函数以及commands模块;也就是说如果你使用的是Python 2.4及以上的版本就应该使用subprocess模块了。
    • 如果你的应用使用的Python 2.4以上,但是是Python 3.5以下的版本,Python官方给出的建议是使用subprocess.call()函数。Python 2.5中新增了一个subprocess.check_call()函数,Python 2.7中新增了一个subprocess.check_output()函数,这两个函数也可以按照需求进行使用。
    • 如果你的应用使用的是Python 3.5及以上的版本(目前应该还很少),Python官方给出的建议是尽量使用subprocess.run()函数。
      当subprocess.call()、subprocess.check_call()、subprocess.check_output()和subprocess.run()这些高级函数无法满足需求时,我们可以使用subprocess.Popen类来实现我们需要的复杂功能。
    subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, universal_newlines=False)
    subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)
    subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)
    subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None)
    subprocess.getstatusoutput(cmd)
    subprocess.getoutput(cmd)
    

    1. subprocess.call()

    其参数可以是一个字符串,也可以是一个列表

    • 返回值是进程的返回值
    • 子进程的输出直接输出到当前的进程输出上
    • 返回值非0,不会抛出异常
    >>> import subprocess
    >>> rescode=subprocess.call("pwd")
    /root
    >>> rescode=subprocess.call(["ls", "*.log"])
    ls: cannot access *.log: No such file or directory
    >>> print(rescode)
    2
    >>> rescode=subprocess.call(args=["echo","python"],timeout=20)
    python
    
    

    如果命令超时会收到subprocess.TimeoutExpired的错误

    2. subprocess.check_all()

    和subprocess.call的区别是

    • 返回值非0,会抛出异常CalledProcessError错误
    >>> rescode=subprocess.check_call(["rm","python.txt"])
    rm: cannot remove ‘python.txt’: No such file or directory
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/python3/lib/python3.7/subprocess.py", line 363, in check_call
        raise CalledProcessError(retcode, cmd)
    subprocess.CalledProcessError: Command '['rm', 'python.txt']' returned non-zero exit status 1.
    >>> 
    >>> rescode
    1
    

    3. subprocess.check_output()

    特点是,

    • 返回值就是子进程的输出,输出是bytes类型
    • 同时获取标准输出和标准错误输出,加上参数stderr=subprocess.STDOUT
    • 命令返回非0,会报错
      演示:
      创建一个叫stdout_err.sh的shell脚本
      脚本内容如下
    echo "stdout content"
    echo "stderr content" 1>&2
    exit 0
    

    将标准输出定向到stdout.txt, 错误输出定向到stderr.txt

    [root@i-5529xjeg ~]# bash stdout_err.sh  1>stdout.txt 2>stderr.txt
    [root@i-5529xjeg ~]# cat stderr.txt 
    stderr content
    [root@i-5529xjeg ~]# cat stdout.txt 
    stdout content
    

    如果不合并标准错误输出到标准输出

    >>> get_res=subprocess.check_output(['bash','stdout_err.sh'])
    stderr content
    >>> get_res
    b'stdout content
    '
    >>> 
    

    如果合并标准错误输出到标准输出

    >>> get_res=subprocess.check_output(['bash','stdout_err.sh'],stderr=subprocess.STDOUT)
    >>> get_res
    b'stdout content
    stderr content
    '
    >>>
    

    4. subprocess.getoutput()

    这个指有输出,不检查返回值

    • 不用担心python抛出错误
    • 没有返回值相关的信息
    >>> get_res=subprocess.getoutput('bash stdout_err.sh')
    >>> get_res
    'stdout content
    stderr content'
    >>> get_res=subprocess.getoutput('fadsfad')
    >>> get_res
    '/bin/sh: fadsfad: command not found'
    >>> 
    

    5. subprocess.getstatusoutput()

    这个比较好

    • 不用担心python抛出异常
    • 有子进程的返回值
    • 有子进程的标准输出和标准错误输出
    • 返回一个元组,第一个值是返回值
    >>> get_res=subprocess.getstatusoutput('ls nonexist.txt')
    >>> get_res
    (2, 'ls: cannot access nonexist.txt: No such file or directory')
    >>>
    

    6. subprocess.Popen() 类

    6.1 args参数是一个字符串的时候必须是可以执行的

    如"ls -l"或者"echo python"都会报错

    >>> get_res=subprocess.Popen('echo python')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/python3/lib/python3.7/subprocess.py", line 800, in __init__
        restore_signals, start_new_session)
      File "/usr/local/python3/lib/python3.7/subprocess.py", line 1551, in _execute_child
        raise child_exception_type(errno_num, err_msg, err_filename)
    FileNotFoundError: [Errno 2] No such file or directory: 'echo python': 'echo python'
    >>> 
    

    加上shell=True就正常

    >>> get_res=subprocess.Popen('echo python',shell=True)
    python
    >>> 
    

    6.2 不加shell=True,需要使用列表传入

    >>> get_res=subprocess.Popen(['echo','python'])
    python
    >>> get_res
    <subprocess.Popen object at 0x7f6f92e306d0>
    >>>
    

    输出定向到文件, 新建test.py文件

    import time,os,sys
    import subprocess
    fd_stdout=open("a.txt","w+")
    po_obj=subprocess.Popen("date",shell=True,stdout=fd_stdout)
    time.sleep(1)
    fd_stdout.close()
    fd_r=open("a.txt","r")
    content=fd_r.read()
    print(u"a.txt包含的内容",content)
    fd_r.close()
    

    如果希望直接得到子进程的输出,而不是通过打开一个文件,可以设定stdout为subprocess.PIPE
    上面的例子可以修改为

    import time,os,sys
    import subprocess
    po_obj=subprocess.Popen("date",shell=True,stdout=subprocess.PIPE)
    time.sleep(1)
    content=po_obj.stdout.read()
    print(u"a.txt包含的内容",content)
    

    类似的也可以设置stdin,这样就可以给子进程输入数据了

    6.3 实例对象的wait()方法

    >>> import subprocess
    >>> po_obj=subprocess.Popen("sleep 1000",shell=True)
    >>> po_obj.returncode is None
    True
    >>> po_obj.pid
    5658
    >>> import os
    >>> os.system("ps 5658")
      PID TTY      STAT   TIME COMMAND
     5658 pts/0    S+     0:00 sleep 1000
    0
    >>> po_obj.kill()
    >>> os.system("ps 5658")
      PID TTY      STAT   TIME COMMAND
     5658 pts/0    Z+     0:00 [sleep] <defunct> #Z+ 表示僵尸状态
    0
    >>> r=po_obj.wait() #处理僵尸进程
    >>> os.system("ps 5658") #进程已经不在了
      PID TTY      STAT   TIME COMMAND
    256
    >>> r  #查看wait()的返回值,就是进程的返回值
    -9
    >>> po_obj.returncode #另外一种方式查看进程的返回值
    -9
    >>> 
    
  • 相关阅读:
    Mac OS X 下安装Raspbian系统
    Tiny4412 uboot Makefile 分析
    Tiny4412增强版底板串口电路与设置
    为Debian搞定Mercury MW150US无线网卡驱动
    树莓派的启动过程
    xml格式转换为Bean
    j2ee之hibernate工具类
    验证码代码
    j2ee之AJAX的二级联动
    j2ee之原生AJAX
  • 原文地址:https://www.cnblogs.com/faberbeta/p/13782227.html
Copyright © 2011-2022 走看看