Python中使用subprocess库创建附加进程


Posted in Python onMay 11, 2021

前言

subprocess库提供了一个API创建子进程并与之通信。这对于运行生产或消费文本的程序尤其有好处,因为这个API支持通过新进行的标准输入和输出通道来回传数据。

本篇,将详细介绍Python创建附加进行的库:subprocess。

run(运行外部命令)

subprocess库本身可以替换os.system(),os.spawnv()等函数。现在我们来通过subprocess库运行一个外部命令,但不采用os.system()。示例如下:

import subprocess

completed = subprocess.run('whoami')
print(completed.returncode)

这里我们运行了一个windows系统常用的whoami命令,返回当前用户的名称,输出如下:

Python中使用subprocess库创建附加进程

这里,我们使用了subprocess.run调用了子进程运行windows命令。它返回一个CompletedProcess实例,它包含了与进行有关的信息。returncode为子进程的退出状态码。通常情况下,退出状态码为0则表示进程成功运行了;一个负值-N表示这个子进程被信号N终止了。

该函数还有许多参数,比如shell,默认值为False表示直接运行命令,如果主动赋值为True则会创建一个中间shell进程,由这个进程运行命令。

import subprocess

completed = subprocess.run('echo 123',shell=True)
print(completed.returncode)

比如这里,我们打印123。

该库还有一个call()函数,subprocess.run有一个check参数,如果没有设置该参数,等价于调用了call()函数。check默认值为False。

对于run()函数启动的进程,它的标准输入输出通道会绑定到父进程的输入输出。这说明调用程序无法捕获命令的输出。不过,我们可以通过为stdout和stderr参数传入PIPE来捕获输出,以备以后处理。

import subprocess

completed = subprocess.run('whoami',stdout=subprocess.PIPE)
print(completed.returncode)
print(len(completed.stdout))
print(completed.stdout.decode('UTF-8'))

运行之后,效果如下:

Python中使用subprocess库创建附加进程

如果设置run()函数的参数check=True与stdout为PIPE,等价于调用了check_output()函数。

通过Shell返回消息

本例会通过一个子shell运行命令,在命令返回错误码并退出之前,将详细输入到控制台。实例如下:

import subprocess

try:
    completed = subprocess.run(
        'echoa 123',
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE, )
except subprocess.CalledProcessError as err:
    print("ERROR:", err)
else:
    print("else")
    print(completed.returncode)
    print(len(completed.stdout))
    print(completed.stdout.decode('UTF-8'))
    print(len(completed.stderr))
    print(completed.stderr.decode('gbk'))

运行之后,效果如下:

Python中使用subprocess库创建附加进程

这里我们输入了一个错误的命令,可以看到因为命令错误,并没有输出命令的执行结果,0和64中间就是completed.stdout,为空。而命令将错误消息返回了。这是因为我们设置了stdout与stderr为subprocess.PIPE,表明这些通道要开放。这样我们才能获取子shell运行的结果获取所运行的错误提示。(读者可以将命令改正确后可以发现错误消息没有了,正确执行结果会输出。这就是subprocess库创建进程的通信机制)

需要注意的是,如果需要抑制输出效果,可以将stdout与stderr设置为subprocess.DEVNULL。不过改了之后,上面代码肯定会报错,因为管道关闭,通信也就关闭了。也就是没有这些参数了。

直接处理管道

subprocess库还有一个非常重要的类Popen,它是用来建立其他API的底层API,对更复杂的进程交互很有用。

比如run(),call(),check_call()和check_output()函数都是Popen类的包装器。直接使用Popen可以更好的控制如何运行命令以及如何处理输入和输出流。Popen的构造函数利用参数建立新进程,使父进程可以通过管道与之通信。

下面,我们来分别介绍进程间通信的方式。

与进程的单项通信

要运行一个进程并读取它的所有输出,可以设置stdout为PIPE并调用communicate()函数。示例如下:

import subprocess

prc = subprocess.Popen('whoami', stdout=subprocess.PIPE)
stdout_value = prc.communicate()[0].decode('utf-8')
print(repr(stdout_value))

如上面代码所示,Popen会在内部管理数据读取。运行之后,效果如下:

Python中使用subprocess库创建附加进程

如果你需要调用一个管道,并完成写数据的操作,可以设置stdin为PIPE。

import subprocess

prc = subprocess.Popen(["cmd", "/c", 'type', '-'], stdin=subprocess.PIPE)
prc.communicate('stdin'.encode('UTF-8'))

与进程的双向通信

要完成进程的双向通信,可以直接将stdin与stdout都设置为PIPE即可。示例如下:

import subprocess

cmd = "cmd /c type E:/Project/debug.log"
cmd.encode('utf-8')
prc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
msg = 'stdin'.encode('UTF-8')
stdout_value = prc.communicate(msg)[0].decode('utf-8')
print(repr(stdout_value))

至于如果命令行错误需要捕获错误消息,可以直接将stderr也设置为PIPE。

连接管道段

在Linux系统中,我们可以将多个命令连接成一个管线,即可以把它们的输入输出串联在一起。通过Popen我们也可以完成类似的操作,只需要将一个Popen实例的stdout属性被用左管线中下一个Popen实例的stdin参数即可。至于最后肯定还是要设置为PIPE,毕竟我们还是要获取多个管道段消息结果,示例如下:

import subprocess

cmd1 = "cmd /c type E:/Project/debug.log"
proc1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE, encoding='utf-8')

cmd2 = "tree /F | findstr 拒绝访问"
proc2 = subprocess.Popen(cmd1, stdout=subprocess.PIPE, stdin=proc1.stdout, encoding='utf-8')

result = proc2.stdout

for line in result:
    print(line.decode('utf-8').strip())

sys的命令交互

在我们学习Python时,一般使用input()进行用户输入数据。但是其实sys库也可以进行输入输出判断,但它涉及的是进程间的交互,示例如下:

import sys

sys.stderr.write('开始\n')
sys.stderr.flush()

while True:
    next_line = sys.stdin.readline()
    sys.stderr.flush()
    if next_line.strip() == "9599":
        break
    sys.stdout.write(next_line)
    sys.stdout.flush()
sys.stderr.write('结束\n')
sys.stderr.flush()

运行之后,效果如下:

Python中使用subprocess库创建附加进程

到此这篇关于Python中使用subprocess库创建附加进程的文章就介绍到这了,更多相关Python附加进程内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python3实现连接SQLite数据库的方法
Aug 23 Python
Python中使用platform模块获取系统信息的用法教程
Jul 08 Python
深入解答关于Python的11道基本面试题
Apr 01 Python
python利用urllib实现爬取京东网站商品图片的爬虫实例
Aug 24 Python
numpy 计算两个数组重复程度的方法
Nov 07 Python
python使用插值法画出平滑曲线
Dec 15 Python
Centos7 下安装最新的python3.8
Oct 28 Python
关于Python 中的时间处理包datetime和arrow的方法详解
Mar 19 Python
关于keras.layers.Conv1D的kernel_size参数使用介绍
May 22 Python
Python logging模块进行封装实现原理解析
Aug 07 Python
Python加密技术之RSA加密解密的实现
Apr 08 Python
Python中的socket网络模块介绍
Jul 23 Python
有趣的二维码:使用MyQR和qrcode来制作二维码
python保存大型 .mat 数据文件报错超出 IO 限制的操作
May 10 #Python
Python批量将csv文件转化成xml文件的实例
python基础之爬虫入门
python设置 matplotlib 正确显示中文的四种方式
提取视频中的音频 Python只需要三行代码!
Python-typing: 类型标注与支持 Any类型详解
May 10 #Python
You might like
PHP生成带有雪花背景的验证码
2008/09/28 PHP
Yii把CGridView文本框换成下拉框的方法
2014/12/03 PHP
Swoole源码中如何查询Websocket的连接问题详解
2020/08/30 PHP
php使用event扩展的io复用测试的示例
2020/10/20 PHP
ie支持function.bind()方法实现代码
2012/12/27 Javascript
Struts2的s:radio标签使用及用jquery添加change事件
2013/04/08 Javascript
jquery 面包屑导航 具体实现
2013/06/05 Javascript
深入解析contentWindow, contentDocument
2013/07/04 Javascript
document.getElementById获取控件对象为空的解决方法
2013/11/20 Javascript
利用js正则表达式验证手机号,email地址,邮政编码
2014/01/23 Javascript
javascript框架设计之类工厂
2015/06/23 Javascript
js实现文本框只允许输入数字并限制数字大小的方法
2015/08/19 Javascript
jQuery通过ajax快速批量提交表单数据
2016/10/25 Javascript
基于vuejs+webpack的日期选择插件
2020/05/21 Javascript
easyui datebox 时间限制,datebox开始时间限制结束时间,datebox截止日期比起始日期大的实现代码
2017/01/12 Javascript
es7学习教程之fetch解决异步嵌套问题的方法示例
2017/07/21 Javascript
Vue2.0 vue-source jsonp 跨域请求
2017/08/04 Javascript
JS 仿支付宝input文本输入框放大组件的实例
2017/11/14 Javascript
vue实现登录后页面跳转到之前页面
2018/01/07 Javascript
微信小程序实现左滑修改、删除功能
2020/10/19 Javascript
Windows下支持自动更新的Electron应用脚手架的方法
2018/12/24 Javascript
JavaScript中工厂函数与构造函数示例详解
2019/05/06 Javascript
详解Vue之事件处理
2020/07/10 Javascript
解决Vue @submit 提交后不刷新页面问题
2020/07/18 Javascript
前端使用crypto.js进行加密的函数代码
2020/08/16 Javascript
Python使用cx_Oracle调用Oracle存储过程的方法示例
2017/10/07 Python
python数据预处理 :样本分布不均的解决(过采样和欠采样)
2020/02/29 Python
房屋改造计划书
2014/01/10 职场文书
《充气雨衣》教学反思
2014/04/07 职场文书
2014公安机关纪律作风整顿思想汇报
2014/09/13 职场文书
高中生国庆节演讲稿范文2014
2014/09/21 职场文书
学校党委干部个人对照检查材料思想汇报
2014/10/09 职场文书
大学生创业,为什么都会选择快餐饮?
2019/08/08 职场文书
JVM入门之类加载与字节码技术(类加载与类的加载器)
2021/06/15 Java/Android
纯CSS3实现div按照顺序出入效果
2021/07/15 HTML / CSS
苹果的回收机器人可以通过拆解iPhone获取大量的金和铜并外公布了环境保护最新进展
2022/04/21 数码科技