subprocess的目的就是启动一个新的进程并且与之通信。

subprocess模块中只定义了一个类: Popen。可以使用Popen来创建进程,并与进程进行复杂的交互。它的构造函数如下:

subprocess.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)

参数args可以是字符串或者序列类型(如:list,元组),用于指定进程的可执行文件及其参数。如果是序列类型,第一个元素通常是可执行文件的路径。我们也可以显式的使用executeable参数来指定可执行文件的路径。

参数stdin, stdout, stderr分别表示程序的标准输入、输出、错误句柄。他们可以是PIPE,文件描述符或文件对象,也可以设置为None,表示从父进程继承。

如果参数shell设为true,程序将通过shell来执行。

参数env是字典类型,用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。

subprocess.PIPE

在创建Popen对象时,subprocess.PIPE可以初始化stdin, stdout或stderr参数。表示与子进程通信的标准流。

subprocess.STDOUT

创建Popen对象时,用于初始化stderr参数,表示将错误通过标准输出流输出。

Popen的方法:

Popen.poll()

用于检查子进程是否已经结束。设置并返回returncode属性。

Popen.wait()

等待子进程结束。设置并返回returncode属性。

Popen.communicate(input=None)

与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。

Popen.send_signal(signal)

向子进程发送信号。

Popen.terminate()

停止(stop)子进程。在windows平台下,该方法将调用Windows API TerminateProcess()来结束子进程。

Popen.kill()

杀死子进程。

Popen.stdin,Popen.stdout ,Popen.stderr ,官方文档上这么说:

stdin, stdout andstderr specify the executed programs’ standard input, standard output and standard error file

handles, respectively. Valid values arePIPE,

an existing file descriptor (a positive integer), an existing file object, and None.

Popen.pid

获取子进程的进程ID。

Popen.returncode

获取进程的返回值。如果进程还没有结束,返回None。

---------------------------------------------------------------

简单的用法:

p=subprocess.Popen("dir", shell=True)

p.wait()

shell参数根据你要执行的命令的情况来决定,上面是dir命令,就一定要shell=True了,p.wait()可以得到命令的返回值。

如果上面写成a=p.wait(),a就是returncode。那么输出a的话,有可能就是0【表示执行成功】。

---------------------------------------------------------------------------

进程通讯

如果想得到进程的输出,管道是个很方便的方法,这样:

p=subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

(stdoutput,erroutput) = p.communicate()

p.communicate会一直等到进程退出,并将标准输出和标准错误输出返回,这样就可以得到子进程的输出了。

再看一个communicate的例子。

上面的例子通过communicate给stdin发送数据,然后使用一个tuple接收命令的执行结果。

------------------------------------------------------------------------

上面,标准输出和标准错误输出是分开的,也可以合并起来,只需要将stderr参数设置为subprocess.STDOUT就可以了,这样子:

p=subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

(stdoutput,erroutput) = p.communicate()

如果你想一行行处理子进程的输出,也没有问题:

p=subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

whileTrue:

buff = p.stdout.readline()

ifbuff ==''andp.poll() !=None:

break

------------------------------------------------------

死锁

但是如果你使用了管道,而又不去处理管道的输出,那么小心点,如果子进程输出数据过多,死锁就会发生了,比如下面的用法:

p=subprocess.Popen("longprint", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

p.wait()

longprint是一个假想的有大量输出的进程,那么在我的xp, Python2.5的环境下,当输出达到4096时,死锁就发生了。当然,如果我们用p.stdout.readline或者p.communicate去清理输出,那么无论输出多少,死锁都是不会发生的。或者我们不使用管道,比如不做重定向,或者重定向到文件,也都是可以避免死锁的。

----------------------------------

subprocess还可以连接起来多个命令来执行。

在shell中我们知道,想要连接多个命令可以使用管道。

在subprocess中,可以使用上一个命令执行的输出结果作为下一次执行的输入。例子如下:

例子中,p2使用了第一次执行命令的结果p1的stdout作为输入数据,然后执行tail命令。

- -------------------

下面是一个更大的例子。用来ping一系列的ip地址,并输出是否这些地址的主机是alive的。代码参考了python unix linux 系统管理指南。

#!/usr/bin/env python

fromthreadingimportThread

importsubprocess

fromQueueimportQueue

num_threads=3

ips=['127.0.0.1','116.56.148.187']

q=Queue()

defpingme(i,queue):

whileTrue:

ip=queue.get()

print'Thread %s pinging %s'%(i,ip)

ret=subprocess.call('ping -c 1 %s'% ip,shell=True,stdout=open('/dev/null','w'),stderr=subprocess.STDOUT)

ifret==0:

print'%s is alive!'%ip

elifret==1:

print'%s is down...'%ip

queue.task_done()

#start num_threads threads

foriinrange(num_threads):

t=Thread(target=pingme,args=(i,q))

t.setDaemon(True)

t.start()

foripinips:

q.put(ip)

print'main thread waiting...'

q.join();print'Done'

在上面代码中使用subprocess的主要好处是,使用多个线程来执行ping命令会节省大量时间。

假设说我们用一个线程来处理,那么每个 ping都要等待前一个结束之后再ping其他地址。那么如果有100个地址,一共需要的时间=100*平均时间。

如果使用多个线程,那么最长执行时间的线程就是整个程序运行的总时间。【时间比单个线程节省多了】

这里要注意一下Queue模块的学习。

pingme函数的执行是这样的:

启动的线程会去执行pingme函数。

pingme函数会检测队列中是否有元素。如果有的话,则取出并执行ping命令。

这个队列是多个线程共享的。所以这里我们不使用列表。【假设在这里我们使用列表,那么需要我们自己来进行同步控制。Queue本身已经通过信号量做了同步控制,节省了我们自己做同步控制的工作=。=】

代码中q的join函数是阻塞当前线程。下面是e文注释

Queue.join()

Blocks until all items in the queue have been gotten and processed(task_done()).

---------------------------------------------

学习Processing模块的时候,遇到了进程的join函数。进程的join函数意思说,等待进程运行结束。与这里的Queue的join有异曲同工之妙啊。processing模块学习的文章在这里

python中subprocess_Python中subprocess学习相关推荐

  1. Python中subprocess学习

    生命不息奋斗不止! subprocess的目的就是启动一个新的进程并且与之通信. subprocess模块中只定义了一个类: Popen.可以使用Popen来创建进程,并与进程进行复杂的交互.它的构造 ...

  2. python中字典和集合的区别_Python中字典和集合学习小结

    映射类型: 表示一个任意对象的集合,且可以通过另一个几乎是任意键值的集合进行索引 与序列不同,映射是无序的,通过键进行索引 任何不可变对象都可用作字典的键,如字符串.数字.元组等 包含可变对象的列表. ...

  3. python神经网络库 keras_在Python和R中使用Keras和Tensorflow进行深度学习

    了解TensorFlow 2.0和Keras在Python和R中的深度学习并构建神经网络 深入了解人工神经网络(ANN)和深度学习 了解Keras和Tensorflow库的用法 了解适用人工神经网络( ...

  4. python中如何编写代码输入多个数据并把它们放在一个列表中去_10分钟学习函数式Python...

    在这篇10分钟的文章中,您将学习Python中的函数式范型.您还将学习列表推导式. 目录 函数式范式 Python的map函数是如何运行的 Python中的lambda表达式 Python中的redu ...

  5. python class def try_python 中exception,class学习

    python 中exception,class 学习 instroduction: Object2 = Object1 ( like java) if Object1 is class object ...

  6. 在学习python的过程中,遇到的最大的困难是什么?

    本人文科生,回顾自己近 2 年的Python 自学经历,有一些学习心得和避坑经验分享给大家,让大家在学习 Python 的过程中少走一些弯路!减少遇到不必要的学习困难! 首先,最开始最大的困难应该就是 ...

  7. python代码:基于强化学习的智能电网的动态定价方法 摘要:提出了一种考虑服务提供商(SP)利润和用户(CUs)成本的分级电力市场中能量管理的动态定价DR算法

    python代码:基于强化学习的智能电网的动态定价方法 摘要:提出了一种考虑服务提供商(SP)利润和用户(CUs)成本的分级电力市场中能量管理的动态定价DR算法. 使用强化学习(RL)描述分层决策框架 ...

  8. python中的模块如何学习_在python中学习队列模块(如何运行它)

    最近引入了队列设计,关于延迟处理能力以及实现"FIFO"等. 查看文档以尝试获取示例队列,以了解如何在我自己的设计/程序中实现它.但我遇到运行此代码的问题: import queu ...

  9. python从零实习深度学习_月薪45K的深度程序员教你从零在Python中开发深度学习

    准备图像数据 我们将使用预训练模型解析图像内容,且目前有很多可选模型.在这种情况下,我们将使用 Oxford isual Geometry Group 或 GG(该模型赢得了 2014 年 Image ...

最新文章

  1. pku 1486 求出二分匹配图中的必须边
  2. 数据库修改后Hibernate的配置更新
  3. 有选择性的启用SAP UI5调试版本的源代码
  4. python正则r的作用_Python正则表达式,这一篇就够了!
  5. python分类下取得所有子类_如何找到给定名称的类的所有子类?
  6. css-第一个CSS
  7. 小笔记,在windows和linux下分开编译、在C\C++下都使用C风格编译
  8. 使用tensorboard可视化tensorflow模型
  9. linux菜鸟要飞-根目录
  10. IHttpModule接口事件执行 获取Session .
  11. AI算法工程师 | 01人工智能基础-快速入门
  12. ansible部署管理k8s
  13. android遍历文件夹里的文件,Android 遍历文件夹中所有文件
  14. 银行c语言面试题,笔试题(商业银行方面)
  15. 智能车过滤阳光_阳光为这辆车加油
  16. JSP的 页面访问执行流程
  17. C++ STL(第十三篇:RB-tree)
  18. 手机号码正则表达式(含虚拟运营商)
  19. python 报 KeyError: ('coupon_type', 'occurred at index act_code')故障
  20. android7.1root工具,Android模拟器Root,Android7.1.1

热门文章

  1. 串口通信模块5:串口操作自定义类(2)
  2. 结合泛型与模板的STL.NET
  3. 用grub4dos修复grub
  4. Delphi开发人员的编程习惯
  5. go语言中错误的处理和实现自己的错误处理类型
  6. python笔记之面向对象
  7. 交换技术、覆盖技术、虚拟存储技术的区分
  8. 十进制数转换为二进制数
  9. 【☀️Linux什么姿势最舒服?简单讲讲☀️】嵌入式Linux入门
  10. update语句的返回值是什么