• Python3 执行系统命令并获取实时回显功能


    Python3 执行系统命令并获取实时回显功能

    def __external_cmd(cmd, code="utf8"):
      print(cmd)
      process = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
      while process.poll() is None:
        line = process.stdout.readline()
        line = line.strip()
        if line:
          print(line.decode(code, 'ignore'))
    

    使用os模块的system方法

    os.system(cmd),只返回状态码,os.system(cmd)会启动子进程,在子进程中执行cmd,如果cmd有执行内容,会在标准输出显示。

    这个调用相当直接,且是同步进行的,程序需要阻塞并等待返回。返回值是依赖于系统的,直接返回系统的调用返回值,所以windows和linux是不一样的。
    在linux中其返回值是shell指令运行后返回的状态码,int类型,0表示shell指令成功执行,256/512表示未找到,该方法适用于shell命令不需要输出内容的场景

    # 列举当前目录下的所有文件
    import os
    val = os.system('ls -al')
    print val #输出为0
    val = os.system('ls -al non_exist_folder')
    print val #输出为512
    val = os.system('ls -al|grep non_exist_val')
    print val #输出为256
    

    使用os.popen()

    只返回信息,该方法以文件的形式返回shell指令运行后的结果,需要获取内容时可使用read()或readlines()方法。

    os.popen(command[,mode[,bufsize]])
    mode – 模式权限可以是 ‘r’(默认) 或 ‘w’。
    bufsize – 指明了文件需要的缓冲大小
    0意味着无缓冲;1意味着行缓冲;
    其它正值表示使用参数大小的缓冲(大概值,以字节为单位)。
    负的bufsize意味着使用系统的默认值,一般来说,对于tty设备,它是行缓冲;对于其它文件,它是全缓冲。如果没有改参数,使用系统的默认值。
    os.popen执行命令是非阻塞的,也就是说不等cmd命令执行完毕就继续下面的代码,但为了能够获取到命令执行结果,可以使用read()或readlines()对命令的执行结果进行读操作,由此产生了阻塞的效果。但是,如果你的命令执行无法退出或进入交互模式,这种“读”将形成完全阻塞的情况,表现的像程序卡住了。
    popen方法通过p.read()获取终端输出,而且popen需要关闭close()。当执行成功时,close()不返回任何值,失败时,close()返回系统返回值。可见它获取返回值的方式和os.system不同。
    

    subprocess模块

    允许创建很多子进程,创建的时候能指定子进程和子进程的输入、输出、错误输出管道,执行后能获取输出结果和执行状态。
    subprocess.Popen():其实以上subprocess使用的方法,都是对subprocess.Popen的封装

    class Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0),Popen对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block)

    1)stdout =subprocess.PIPE 与 stderr=subprocess.PIPE ,python 2中返回字符串,python 3中返回字节形式的结果

    #python 3>>> res = subprocess.Popen("ls /tmp/", shell=True, stdout=subprocess.PIPE) # 使用管道
    >>> res.stdout.read()  # 标准输出
    b'/tmp/yum.log\n'
    res.stdout.close()  # 关闭
    >>> 
    >>> res = subprocess.Popen("lm -l",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)# 标准输出为空
    >>> res.stdout.read()
    b''#标准错误中有错误信息
    >>> res.stderr.read()
    b'/bin/sh: lm: command not found\n'
    

    2)poll() 定时检查命令有没有执行完毕,执行完毕后返回执行结果的状态,没有执行完毕返回None

    3)wait()等待命令执行完成,并且返回结果状态

    4 ) terminate() 结束进程

    5)pid 获取当前执行子shell的程序的进程号

    说明: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)

       args:表示shell指令,若以字符串形式给出shell指令,如"ls -l "则需要使shell = Ture。否则默认以数组形式表示shell变量,如"ls","-l"。

       当使用比较复杂的shell语句时,可以先使用shlex模块的shlex.split()方法来帮助格式化命令,然后在传递给run()方法或Popen。

    subprocess.run()、subprocess.call()、subprocess.check_call()、subprocess.check_output()都是通过对subprocess.Popen的封装来实现的高级函数,因此如果我们需要更复杂功能时,可以通过subprocess.Popen来完成

    复制代码
    import shlex
    import subprocess
    command='ls -l'
    args=shlex.split('ls -l')
    bb=subprocess.Popen(args) #bb是一个Popen的对象,该对象不能通过read()或readlines()来读取
    输出:total 0
    -rw-rw-r-- 1 roaddb roaddb 0 Dec 11 10:09 a.txt
    -rw-rw-r-- 1 roaddb roaddb 0 Dec 11 10:09 b.txt #在该处需要点击换行符才会结束
    aa=subprocess.call('ls -l',shell=True)  #其返回值为shell命令的执行返回码
    输出:total 0
    -rw-rw-r-- 1 roaddb roaddb 0 Dec 11 10:09 a.txt
    -rw-rw-r-- 1 roaddb roaddb 0 Dec 11 10:09 b.txt #直接返回
    
    

    参考:
    https://www.cnblogs.com/mianbaoshu/p/12024498.html

    https://blog.csdn.net/StephenHendery/article/details/118760475

    https://cloud.tencent.com/developer/article/1570965

    https://python3-cookbook.readthedocs.io/zh_CN/latest/c13/p06_executing_external_command_and_get_its_output.html

    https://www.cnblogs.com/lincappu/p/8270709.html

  • 相关阅读:
    MatOfPoint作为minAreaRect的参数总是报错"throw new IllegalArgumentException("Incomatible Mat");
    !! Android developer 最新国内镜像
    下载安装和OpenCV匹配的Android开发环境
    Android View的onTouchEvent和OnTouch区别
    org.opencv.android.JavaCameraView 摄像机方向的问题
    C语言 · 数字三角形
    C语言 · Torry的困惑(基本型)
    C语言 · 高精度加法
    C语言 · Anagrams问题
    C语言 · 字符串对比
  • 原文地址:https://www.cnblogs.com/michaelcjl/p/16647007.html
Copyright © 2020-2023  润新知