【Python】 子进程创建与使用subprocess

subprocess

*****本文参考了Vamei大神的http://www.cnblogs.com/vamei/archive/2012/09/23/2698014.html  

 运用subprocess包可以在运行python的进程下进一步开启一个子进程,创建子进程要注意

    1. 父进程是否暂停

    2.创建出的子进程返回了什么

    3.执行出错,即返回的code不是0的时候应该如何处理

  subprocess包提供了三个开启子进程的方法,subprocess.call() , subprocess.check_call() , subprocess.check_output(),给三者传递命令字符串作为参数。可以用(['ping','www.baidu.com','-c','3'])这种列表的形式,同时也可以是("ping www.baidu.com -c 3") 这种形式。在开启子进程的时候,可以加上shell=True的参数来让python开启一个shell,通过shell来解释获得的命令。一般在windows下运行的程序最好都把shell=True加上,这样才能顺利地执行dos命令,但是linux下似乎不加也没啥关系。因为linux下未指明用shell执行的话会调用/bin/sh来执行,问题不大,但是dos下系统不会默认用cmd.exe来执行命令,所以要加上shell=True。

  subprocess.call ; subprocess.check_call ; subprocess.check_output  这三者的区别在于,返回的值分别是,子进程的执行返回码;若返回码是0则返回0,否则出错的话raise起CalledProcessError,可以用except处理之;若返回码是0则返回子进程向stdout输出的结果,否则也raise起CalledProcessError。另外,这三个方法都是让父进程挂起等待的,在子进程结束之前,父进程不会继续往下运行。

  另外从本质上讲,上述三个方法都是对subprocess.Popen方法的一个包装,Popen开启的子进程是不会让父进程等待其完成的,除非调用了wait()方法:

child = subprocess.Popen("...",shell=True)
print "Hello"
"""
很可能hello在子进程的输出之前就被打印出来了,因为父进程不等child子进程运行完
"""child = subprocess.Popen("...",shell=True)
child.wait()
print "Hello"
"""
这就不一样,父进程一定会等子进程运行完,给出完整的结果之后再继续往下执行。相当于wait函数挂起了父进程。
"""

   此外,上面代码里的child这个对象还有其他的一些方法:

    child.poll()  返回子进程运行状态,主要是两种结果,None代表尚未运行完,而一个返回码则代表已经运行完成并且是成功或失败了

    child.kill()  强行终止子进程

    child.send_signal(...)  向子进程发送一个信号(具体信号是以什么方式表示不清楚,还待研究

    child.terminate()  终止子进程

    child.pid  子进程的pid

    child.returncode  子进程的返回码

    child.stdin/stdout/stderr    子进程的标准输入流,标准输出和标准错误输出,都是类文件对象

 

■  文本流控制

  每个子进程对象都有stdin/stdout/stderr三个对象,而在Popen开启子进程的时候,可以设置这三个对象。比如

child1 = subprocess.Popen("cmd1",shell=True, stdout=subprocess.PIPE)
'''
child1的stdout被设置成管道,可以把它理解成一个第三方托管机构,
因为不设置的话child1的stdout的内容就直接被打印到父进程的stdout里了,
设置成管道之后内容被导入了PIPEという名の第三方托管机构里
'''
child2 = subprocess.Popen("cmd2",shell=True,stdin=child1.stdout,stdout=subprocess.PIPE)
'''
把child2的stdin设置成了child1的stdout,也就是之前那个第三方机构,这么一来就实现了两个子进程之间的数据通信了。
而把child2的stdout也设置成第三方,是因为不想让child2的输出就直接这么输出到父进程的stdout里,而要对它做一些处理
''' stdout,tmp = child2.communicate() ''' 因为child2的输出不用再转给个child3去处理,就用communicate方法把第三方机构那里的数据取出来放进一个变量里。
注意,这里的stdout已经是个str对象了,communicate出来的都是字符串了
communicate方法自带wait功能,会让父进程挂起等待所有子进程结束
communicate会返回一个元组,但是像在这个例子中没有设置stderr=PIPE,所以元组中的第二项原本属于stderr的值的地方的tmp的值是None,如果设置了其为PIPE,由于没有错误信息tmp是""。这点是有区别的。
''' print "We have result:\n%s"%(stdout) #代表了把stdout做一些处理后再输出

 

 ■  Popen方法

  Popen就是开启一个新的子进程,常用的几个参数正如上面所提的cmd,shell,stdin,stdout,stderr来指定开启的子进程的一些属性。

  除此之外还有以下的参数:

    close_fds  默认为False,设置为True的情况下会在子进程执行之前关闭所有除了0,1,2之外的所有文件都关闭(虽然不知道有什么意义)

    cwd  默认None,可以为子进程设置工作目录

  盗了张图(http://www.cnblogs.com/zhoug2020/p/5079407.html)

  

 

  实际上,我一般都是这么干的:

import subprocessp = subprocess.Popen("CMD",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout,stderr = p.communicate()
if stderr != "":print "ERROR:"+stderr
elseprint "RESULT:"+stdout

 

*这篇文章(http://www.tuicool.com/articles/bUNJ7v)提供了一个解决大量并发开启子进程时出bug的方案,同时也给了一个如何为一个子进程设置超时的方法,值得看一下:

def timeout_command(command, timeout):start = datetime.datetime.now()process = subprocess.Popen(command, bufsize=10000, stdout=subprocess.PIPE, close_fds=True)'''这个循环就是为子进程设置了超时功能,感觉还挺巧妙的。。'''while process.poll() is None:time.sleep(0.1)now = datetime.datetime.now()if (now - start).seconds> timeout:try:process.terminate()except Exception,e:return Nonereturn Noneout = process.communicate()[0]if process.stdin:process.stdin.close()if process.stdout:process.stdout.close()if process.stderr:process.stderr.close()try:process.kill()except OSError:passreturn out

 ■  关于实时获取子进程输出的方法

  之前用过的所有subprocess.Popen方法吧,打开的子进程都比较短小,其命令基本上都可以在一秒内完成。所以在communicate的时候都没有显示出什么不妥的地方。但是碰到一些比较大,运行时间比较长的命令时,communicate就显得有些不太好了,因为到命令运行完成或者缓冲区满为止,子进程对象是不会向程序返回输出内容的。此时就需要变通一点不要使用communicate了。

  一个解决的办法是这样的:

import subprocess
import sysp = subprocess.Popen('cmd',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)while p.poll() is None:    #当子进程没有完成之前char = p.stdout.read(1)sys.stdout.write(char)stdout,stderr = p.communicate()
sys.stdout.write(stdout)

 

  观察这段程序,可以看到,当子进程没有结束之前,循环将不断地从子进程的stdout中读取一个字符的数据然后写到父进程的stdout中。如果子进程较长时间没有明文进入stdout的话也可以在循环中加上一个time.sleep来控制循环频率。下面再加上communicate是为了保证信息输出的完整性。因为当子进程结束之后,有可能stdout还没有读取光,如果不加communicate的话那么还剩余在stdout中的信息就丢失了。如果子进程在stderr中有输出那么也可以放在communicate后面判断。另外也可以在建立p对象的时候把stderr参宿设置为subprocess.STDOUT来把子进程的stderr输出重定向到stdout中。

  *测试的时候,把一个每sleep1秒就向stdout写入一些信息的脚本当做子进程。但是发现以上方法并不奏效。想了下之后,记起来python在写文件的时候是会有缓冲区这个设定的。也就是说,子进程代码中的write被调用后stdout并不马上把信息输出到stdout中。解决办法就是用file对象(这里是sys.stdout)调用flush()方法来清空缓存并写入文件。

 

转载于:https://www.cnblogs.com/franknihao/p/6537159.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/393542.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

lrzsz   linux与windows互传

2019独角兽企业重金招聘Python工程师标准>>> lrzsz linux与windows互传 # 前提是使用 xshell 或者 securecrt 这两个远程软件,putty不支持 yum install -y lrzsz //安装文件包 linux向windows 传文件使用 : sz 文件名 回…

Spring: (一) -- 春雨润物之 核心IOC

作为一个Java人,想必都或多或少的了解过Spring。对于其优势也能道个一二,诸如方便解耦、支持AOP编程、支持声明式事务、方便测试等等。Spring也不仅仅局限于服务器端开发,它可以做非常多的事情,任何Java应用都可以在简单性、可测试…

XUbuntu22.04之跨平台音频编辑工具(平替Audition):ocenaudio(二百零二)

加粗样式 简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏&#…

mysql 从服务器同步设置_mysql主从同步配置

1.为什么要主从同步?在Web应用系统中,数据库性能是导致系统性能瓶颈最主要的原因之一。尤其是在大规模系统中,数据库集群已经成为必备的配置之一。集群的好处主要有:查询负载、数据库复制备份等。其中Master负责写操作的负载&…

每天一个LINUX命令(pwd)

每天一个LINUX命令(pwd) 基本信息 pwd: /bin/pwd,显示当前路径的绝对路径 语法:pwd 应用程序位置 which pwd PWD作用 pwd --help或者man pwd PWD的使用 pwd 转载于:https://www.cnblogs.com/shanshanliu/p/6542403.html

一个swiper 两个分页器的写法【总结】

写项目的时候&#xff0c;使用的是swiper插件呈现的效果是一个swiper要实现两个分页器&#xff0c;下面就来总结一下 以swiper3为例来写&#xff0c;在页面中引入jquery、swiper.min.js和swiper.min.css文件。 HTML结构&#xff1a; <div class"banner swiper-containe…

python 爬虫可视化编程_Python爬虫爬取博客实现可视化过程解析

源码&#xff1a;from pyecharts import Barimport reimport requestsnum0b[]for i in range(1,11):linkhttps://www.cnblogs.com/echoDetected/default.html?pagestr(i)headers{user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko…

linux 一键安装lnmp

运行下面这天命令&#xff0c;回车 wget http://soft.vpser.net/lnmp/lnmp1.5.tar.gz -cO lnmp1.5.tar.gz && tar zxf lnmp1.5.tar.gz && cd lnmp1.5 && ./install.sh lnmp 选择数据库版本&#xff0c;回车 设置MySQL的root密码&#xff08;为了安全不…

PHP上传文件到七牛云和阿里云

七牛云上传 注册七牛云账号并认证 进入控制台找到对象存储添加一个新的仓库 添加完成之后看文档 安装 使用 Composer 安装 Composer是 PHP 依赖管理工具。你可以在自己的项目中声明所依赖的外部工具库&#xff0c;Composer 会自动帮你安装这些依赖的库文件。    1. 安装…

变态青蛙跳

2019独角兽企业重金招聘Python工程师标准>>> 题目描述 一只青蛙一次可以跳上1级台阶&#xff0c;也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。 相比普通青蛙跳&#xff0c;这个 n级的就有点难了&#xff0c;重点是 能跳n级&…

Django——认证系统(Day72)

阅读目录 COOKIE 与 SESSION 用户认证 COOKIE 与 SESSION 概念 cookie不属于http协议范围&#xff0c;由于http协议无法保持状态&#xff0c;但实际情况&#xff0c;我们却又需要“保持状态”&#xff0c;因此cookie就是在这样一个场景下诞生。 cookie的工作原理是&#xff1a;…

12-1 12 防盗链 访问控制 php解析 代理

2019独角兽企业重金招聘Python工程师标准>>> 12.13 Nginx防盗链 12.14 Nginx访问控制 12.15 Nginx解析php相关配置 12.16 Nginx代理 扩展 502问题汇总 http://ask.apelearn.com/question/9109location优先级 http://blog.lishiming.net/?p10012.13 Nginx防盗链 用来…

图片预览------photoswipe 使用

photoswipe 使用 预览图片后&#xff0c;需要点击关闭按钮才能关闭&#xff0c;点击图片事件效果是放大图片&#xff0c;和微信的效果不一致&#xff0c;最后改用微信预览图片的接口了&#xff0c;但是例子可以用&#xff0c;记录一下&#xff01;&#xff01; http://www.cnbl…

SSKeychain

Keychain 使用? ---为了实用最大化我觉得我应该直接先说使用&#xff01; 当然是使用第三方库啦&#xff1a;sskeychain 3000星星的库不开玩笑。github地址&#xff1a;https://github.com/soffes/sskeychain 导入完之后首先&#xff0c;编译一下有无错。 如果是自己手动导入&…

linux mysql提交_MySQL 事务提交过程

开发老大要求通过binlog查询一条被修改的数据&#xff0c;数据被查出后问我&#xff0c;有没有可能binlog中不会记录&#xff0c;回答不会&#xff0c;因为数据被修改&#xff0c;若失败直接回滚&#xff0c;不会在binlog中记录&#xff0c;此刻一个朋友用了洪荒之力告诉我&…

React单元测试:Jest + Enzyme(二)

前言 在上一篇教程中&#xff0c;我们成功搭建了基于Jest和Enzyme的单元测试框架并成功地跑起来第一个单元测试&#xff0c;可以点击这里回顾一下。今天&#xff0c;我们重点讨论如何通过Jest来mock数据。 什么是Mock Mock的简单翻译就是模拟。既可以模拟数据&#xff0c;也可以…

python dict hash算法_2020年3月26日python学习笔记——hash

什么是哈希&#xff1f;hash,一般翻译做散列、杂凑&#xff0c;或音译为哈希&#xff0c;是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出&#xff0c;该输出就是散列值。这种转换是一种压缩映射&#xff0c;也就是&#xff0c;散列值的空间通常远…

数据处理不等式:Data Processing Inequality

我是在差分隐私下看到的&#xff0c;新解决方案的可用性肯定小于原有解决方案的可用性&#xff0c;也就是说信息的后续处理只会降低所拥有的信息量。 那么如果这么说的话为什么还要做特征工程呢&#xff0c;这是因为该不等式有一个巨大的前提就是数据处理方法无比的强大&#x…

gulp 实现sass自动化 ,监听同步

实现功能 监听scss文件   sass自动化 准备条件 1 .安装gulp npm init ---->一直enter&#xff0c;会在当前目录下生成一个package.json文件,记录安装的依赖模块 npm install gulp --save-dev 2 .安装gulp-ruby-sass npm install gulp-ruby-sass 你还需要安装ruby环境…

MSSQL → 02:数据库结构

一、数据库的组成 在SQL Server 2008中&#xff0c;用户如何访问及使用数据库&#xff0c;就需要正确了解数据库中所有对象及其设置。数据库就像一个容器&#xff0c;它里面除了存放着数据的表之外&#xff0c;还有视图、存储过程、触发器、约束等数据库对象。数据库管理的核心…