【Python】subprocess子进程管理

来源,之前在通过ffmpeg获取视频时长的时候遇到以下代码,对 subprocess.Popen() 的使用分析一下。

def getLenTime(filename):
    # 这个list其实等于"ffprobe.exe -loglevel quiet -print_format json -show_format -show_streams -i <input video>"
    command = ["ffprobe.exe","-loglevel","quiet","-print_format","json","-show_format","-show_streams","-i",filename]
    """
注意:这是在windows环境下!!!
    # shell=True 如果该参数为 True,将通过操作系统的 shell 执行指定的命令;
    # subprocess.PIPE 表示为子进程创建新的管道;
    # stderr错误句柄,subprocess.STDOUT 标准输出,stderr 可以合并到 stdout 里一起输出;
    # 被调用时指定stderr=subprocess.STDOUT,那么stdout和stderr将会被整合到这一个属性中,且stderr将会为None;
    # stdout 参数是 PIPE,此属性是一个类似 open() 返回的可读流。从流中读取子进程提供的输出。
    # 以下命令的含义是:运行command shell语句,将运行的结果(连同报错信息)一起写入到二进制文件流中,并返回给result接收。
    """
    result = subprocess.Popen(command,shell=True,stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
    # 读取结果
    out = result.stdout.read()
    # print(str(out))  # 二进制的文件流,b'{xxxx}
    temp = str(out.decode('utf-8'))
    # print(temp) # 有视频的详细信息,以json格式存储
    data = json.loads(temp)["format"]['duration']
    return float(data)

定义:subprocess 模块允许我们启动一个新进程,并连接到它们的输入/输出/错误管道,从而获取返回值。

Popen() 方法

Popen 是 subprocess的核心,子进程的创建和管理都靠它处理。

构造函数:

class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None,
 stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, 
universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True, 
start_new_session=False, pass_fds=(), *, encoding=None, errors=None, text=None)

常用参数:

  • args:shell命令,可以是字符串或者序列类型(如:list,元组)
  • bufsize:缓冲区大小。当创建标准流的管道对象时使用,默认-1。
    0:不使用缓冲区
    1:表示行缓冲,仅当universal_newlines=True时可用,也就是文本模式
    正数:表示缓冲区大小
    负数:表示使用系统默认的缓冲区大小。
  • stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
  • preexec_fn:只在 Unix 平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
  • shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令。
  • cwd:用于设置子进程的当前目录。
  • env:用于指定子进程的环境变量。如果 env = None,子进程的环境变量将从父进程中继承。

Popen.stdin

如果 stdin 参数为 PIPE,此属性是一个类似 open() 返回的可写的流对象。如果 encoding 或 errors 参数被指定或者 universal_newlines 参数为 True,则此流是一个文本流,否则是字节流。如果 stdin 参数非 PIPE, 此属性为 None

Popen.stdout

如果 stdout 参数是 PIPE,此属性是一个类似 open() 返回的可读流。从流中读取子进程提供的输出。如果 encoding 或 errors 参数被指定或者 universal_newlines 参数为 True,此流为文本流,否则为字节流。如果 stdout 参数非 PIPE,此属性为 None

Popen.stderr

如果 stderr 参数是 PIPE,此属性是一个类似 open() 返回的可读流。从流中读取子进程提供的输出。如果 encoding 或 errors 参数被指定或者 universal_newlines 参数为 True,此流为文本流,否则为字节流。如果 stderr 参数非 PIPE,此属性为 None

实例

>>> import subprocess
>>> p = subprocess.Popen('ls -l', shell=True)  #  p = subprocess.Popen(['ls', '-cl']) 
>>> total 164
-rw-r--r--  1 root root   133 Jul  4 16:25 admin-openrc.sh
-rw-r--r--  1 root root   268 Jul 10 15:55 admin-openrc-v3.sh
...
>>> p.returncode
>>> p.wait()
0
>>> p.returncode

这里也可以使用 p = subprocess.Popen(['ls', '-cl']) 来创建子进程。

Popen 对象方法

  • poll(): 检查进程是否终止,如果终止返回 returncode,否则返回 None。
  • wait(timeout): 等待子进程终止。
  • communicate(input,timeout): 和子进程交互,发送和读取数据。
  • send_signal(singnal): 发送信号到子进程 。
  • terminate(): 停止子进程,也就是发送SIGTERM信号到子进程。
  • kill(): 杀死子进程。发送 SIGKILL 信号到子进程。

实例

import time
import subprocess

def cmd(command):
    subp = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding="utf-8")
    subp.wait(2)
    if subp.poll() == 0: # 检查进程是否终止,如果终止返回 returncode,否则返回 None
        print(subp.communicate()[1]) # 和子进程交互,发送和读取数据。
    else:
        print("失败")



cmd("java -version")
cmd("exit 1")

输出结果如下:

java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

失败

参考:

Python3 subprocess

https://docs.python.org/zh-cn/3/library/subprocess.html

源代码: Lib/subprocess.py

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值