subprocess?Python中subprocess模块用法实例详解
大家好,今天小编来为大家解答subprocess这个问题,Python中subprocess模块用法实例详解很多人还不知道,现在让我们一起来看看吧!
subprocess的popen函数
subprocess的进程创建和管理由Popen类处理。原型:(原型中参数带有的值都是默认值)
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=(), *, group=None, extra_groups=None, user=None, umask=-1, encoding=None, errors=None, text=None)
args参数:一个需要运行的参数序列;默认情况下,如果args是序列,则运行的程序是这个序列中的第一项,比如[“python”,“--version”],运行的cmd就是这个列表中的第一项python;但是如果args是字符串,具体如何实现依赖于具体平台。如果在Windows上 shell 为 False 并且序列包含字节串和路径类对象则 args 形参可以接受一个 path-like object。参数 shell (默认为 False)指定是否使用 shell执行程序。如果 shell 为 True,更推荐将 args 作为字符串传递而非序列。如果 args 是一个字符串,则字符串的格式必须和在命令行中所输出的完全相同。在 Windows,使用 shell=True,环境变量 COMSPEC 指定了默认 shell。在 Windows唯一需要指定 shell=True 的情况是想要执行内置在 shell中的命令(例如 dir 或者 copy)。在运行一个批处理文件或者基于控制台的可执行文件时,不需要 shell=True。
def cmd_run(cmd):
print("the cmd is{}".format(cmd))
subproc= subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP, shell=True)#设置shell为true
while True:
out= subproc.stdout.readline()
if out:
print(out)
else:
break
cmd_run("dir")
输出:
如果没有设置shell为True,则在windows上无法运行这个cmd。
executable 参数指定一个要执行的替换程序,比较少用到这个参数。当 shell=True, executable 替换 args 指定运行的程序。但是,原始的 args 仍然被传递给程序。
在 3.6版更改: 在POSIX上 executable 形参可以接受一个 path-like object。
在 3.8版更改: 在Windows上 executable 形参可以接受一个字节串和 path-like object。
stdin, stdout 和 stderr 分别指定被运行的程序的标准输入、输出和标准错误的文件句柄。合法的值有 PIPE , DEVNULL ,一个存在的文件描述符(一个正整数),一个存在的 文件对象 以及 None。 PIPE 表示应创建一个新的对子进程的管道。 DEVNULL 表示使用特殊的 os.devnull 文件。使用默认的 None,则不进行成定向;子进程的文件流将继承自父进程。另外, stderr 可设为 STDOUT,表示应用程序的标准错误数据应和标准输出一同捕获。
如果 close_fds 为真,所有文件描述符除了 0, 1, 2 之外都会在子进程执行前关闭。而当 close_fds 为假时,文件描述符遵守它们继承的标志如 文件描述符的继承 所述。在 Windows,如果 close_fds 为真,则子进程不会继承任何句柄,除非在 STARTUPINFO.IpAttributeList的 handle_list的键中显式传递,或者通过标准句柄重定向传递。
如果 cwd 不为 None,此函数在执行子进程前会将当前工作目录改为 cwd。 cwd 可以是一个字符串、字节串或 路径类对象 。特别地,当可执行文件的路径为相对路径时,此函数会相对于*cwd*来查找 executable (或 args 中的第一个条目)。
在 3.6版更改: 在 POSIX上 cwd 形参接受一个 path-like object。
在 3.7版更改: 在 Windows上 cwd 形参接受一个 path-like object。
在 3.8版更改: 在 Windows上 cwd 形参接受一个字节串对象。
如果 encoding 或 errors 被指定,或者 text 为 true,则文件对象 stdin, stdout 和 stderr 将会以指定的编码和 errors 以文本模式打开,如同 常用参数 所述。
universal_newlines 参数等同于 text 并且提供向后兼容性。默认情况下,文件对象都以二进制模式打开。
如果给出, startupinfo 将是一个将被传递给底层的 CreateProcess 函数的 STARTUPINFO 对象。
creationflags,如果给出,可以是一个或多个以下标志之一:
CREATE_NEW_CONSOLE
CREATE_NEW_PROCESS_GROUP
ABOVE_NORMAL_PRIORITY_CLASS
BELOW_NORMAL_PRIORITY_CLASS
HIGH_PRIORITY_CLASS
IDLE_PRIORITY_CLASS
NORMAL_PRIORITY_CLASS
REALTIME_PRIORITY_CLASS
CREATE_NO_WINDOW
DETACHED_PROCESS
CREATE_DEFAULT_ERROR_MODE
CREATE_BREAKAWAY_FROM_JOB
Popen对象支持通过 with 语句作为上下文管理器,在退出时关闭文件描述符并等待进程:。
在 3.6版更改: 现在,如果 Popen析构时子进程仍然在运行,则析构器会发送一个 ResourceWarning 警告。
在 3.8版更改: 在某些情况下 Popen可以使用 os.posix_spawn() 以获得更好的性能。在适用于 Linux的 Windows子系统和 QEMU用户模拟器上,使用 os.posix_spawn() 的 Popen构造器不再会因找不到程序等错误而引发异常,而是上下级进程失败并返回一个非零的 returncode。
异常
在子进程中抛出的异常,在新的进程开始执行前,将会被再次在父进程中抛出。
最常见的被抛出异常是 OSError。例如,当尝试执行一个不存在的文件时就会发生。应用程序需要为 OSError 异常做好保护。
如果 Popen 调用时有无效的参数,则一个 ValueError 将被抛出。
check_all() 与 check_output() 在调用的进程返回非零退出码时将抛出 CalledProcessError。
所有接受 timeout 形参的函数与方法,例如 call() 和 Popen.communicate() 将会在进程退出前超时到期时抛出 TimeoutExpired。
此模块中定义的异常都继承自 SubprocessError。
Python中subprocess模块用法实例详解
本文实例讲述了Python中subprocess模块用法。分享给大家供大家参考。
具体如下:
执行命令:
?
1
2
3
4
subprocess.call([ls,-l])
0
subprocess.call(exit 1, shell=True)
1
测试调用系统中cmd命令,显示命令执行的结果:
?
1
2
3
x=subprocess.check_output([echo, Hello World!],shell=True)
print(x)
Hello World!
测试在python中显示文件内容:
?
1
2
3
4
5
y=subprocess.check_output([type, app2.cpp],shell=True)
print(y)
#include iostream
using namespace std;
......
查看ipconfig-all命令的输出,并将将输出保存到文件tmp.log中:
?
1
2
handle= open(rd:tmp.log,wt)
subprocess.Popen([ipconfig,-all], stdout=handle)
查看网络设置ipconfig-all,保存到变量中:
?
output= subprocess.Popen([ipconfig,-all], stdout=subprocess.PIPE,shell=True)
oc=output.communicate()#取出output中的字符串
#communicate() returns a tuple(stdoutdata, stderrdata).
print(oc[0])#打印网络信息
Windows IP Configuration
Host Name.....
我们可以在Popen()建立子进程的时候改变标准输入、标准输出和标准错误,并可以利用subprocess.PIPE将多个子进程的输入和输出连接在一起,构成管道(pipe):
?
1
2
3
4
5
child1= subprocess.Popen([dir,/w], stdout=subprocess.PIPE,shell=True)
child2= subprocess.Popen([wc], stdin=child1.stdout,stdout=subprocess.PIPE,shell=True)
out= child2.communicate()
print(out)
( 9 24 298n, None)
如果想频繁地和子线程通信,那么不能使用communicate();因为communicate通信一次之后即关闭了管道.这时可以试试下面的方法:
11
12
13
14
p= subprocess.Popen([wc], stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True)
p.stdin.write(your command)
p.stdin.flush()
#......do something
try:
#......do something
p.stdout.readline()
#......do something
except:
print(IOError)
#......do something more
p.stdin.write(your other command)
p.stdin.flush()
#......do something more
希望本文所述对大家的Python程序设计有所帮助。
python subprocess怎样才能 popen的进程
在收集snmp数据的过程中用到了subprocess这个模块,本来想用其他python里面关于snmp的库,还是觉得麻烦就直接调用snmpwalk来收集数据。
最开始想用subprocess.call()这个函数,然而这个函数没有和其他进程通信的功能就放弃了
google了一下找到subprocess.Popen()这个函数,具体用法后面会贴一个别人写的帖子
其中subprocess.PIPE类似于pipe()系统调用,不过不需要指定PID,只需要把stdout,stdin,error指定为subprocess.PIPE就可以了
我写的这个小脚本里面有参数shell=True,意思是通过shell执行命令而不是直接的execvp()
#!/usr/bin/env python
# gathering snmp data
import subprocess
import os
cmd="snmpwalk-v 2c ip-c group"
fd=open("/home/user/snmptest","w")
data=subprocess.Popen(cmd,stdout=subprocess.PIPE,shell=True)
fd.write(data.stdout.read())
fd.close()
执行之后snmptest里面就写入了收集来的snmp数据
另外贴一个别人总结的subprocess的使用方法
Python模块学习---- subprocess创建子进程
最近,我们老大要我写一个
守护者程序,对服务器进程进行守护。如果服务器不幸挂掉了,守护者能即时的重启应用程序。上网Google了一下,发现Python有很几个模块都可以创
建进程。最终我选择使用subprocess模块,因为在Python手册中有这样一段话:
This module intends to replace several
other, older modules and functions, such as:
os.system、os.spawn*、os.popen*、popen2.*、commands.*
subprocess被用来替换一些老的模块和函数,如:os.system、 os.spawn*、os.popen*、popen2.*、commands.*。可见,subprocess是被推荐使用的模块。
下面是一个很简单的例子,创建一个新进程,执行app1.exe,传入相当的参数,并打印出进程的返回值:
import subprocess
returnCode= subprocess.call('app1.exe-a-b-c-d')
print'returncode:', returnCode
#-----结果--------
#Python is powerful
#app1.exe
#-a
#-b
#-c
#-d
returncode: 0
app1.exe是一个非常简单的控制台程序,它只打印出传入的参数,代码如下:
#include
using namespace std;
int main(int argc, const char*argv[])
{
cout<<"Python is powerful"<< endl;
for(int i= 0; i< argc; i++)
{
cout<< argv[i]<< endl;
}
return 0;
}
闲话少说,下面开始详细介绍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参数来指定可执行文件的路径。在windows操作系统上,Popen通过调用
CreateProcess()来创建子进程,CreateProcess接收一个字符串参数,如果args是序列类型,系统将会通过
list2cmdline()函数将序列类型转换为字符串。
参数bufsize:指定缓冲。我到现在还不清楚这个参数的具体含义,望各个大牛指点。
参数executable用于指定可执行程序。一般情况下我们通过args参数来设置所要运行的程序。如果将参数shell设为 True,executable将指定程序使用的shell。在windows平台下,默认的shell由COMSPEC环境变量来指定。
参数stdin, stdout, stderr分别表示程序的标准输入、输出、错误句柄。他们可以是PIPE,文件描述符或文件对象,也可以设置为None,表示从父进程继承。
参数preexec_fn只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用。
参数Close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管
道。我们不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。
如果参数shell设为true,程序将通过shell来执行。
参数cwd用于设置子进程的当前目录。
参数env是字典类型,用于指定子进程的环境变量。如果env= None,子进程的环境变量将从父进程中继承。
参数Universal_newlines:不同操作系统下,文本的换行符是不一样的。如:windows下用'\r\n'表示换,而Linux下用'\n'。如果将此参数设置为True,Python统一把这些换行符当作'\n'来处理。
参数startupinfo与createionflags只在windows下用效,它们将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等。
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对象是,参数stdin被设置为PIPE,Popen.stdin将返回一个文件对象用于策子进程发送指令。否则返回None。
Popen.stdout
如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回 None。
Popen.stderr
如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回 None。
Popen.pid
获取子进程的进程ID。
Popen.returncode
获取进程的返回值。如果进程还没有结束,返回None。
下面是一个非常简单的例子,来演示supprocess模块如何与一个控件台应用程序进行交互。
import subprocess
p= subprocess.Popen("app2.exe", stdin= subprocess.PIPE,\
stdout= subprocess.PIPE, stderr= subprocess.PIPE, shell= False)
p.stdin.write('3\n')
p.stdin.write('4\n')
print p.stdout.read()
#----结果----
input x:
input y:
3+ 4= 7
app2.exe也是一个非常简单的控制台程序,它从界面上接收两个数值,执行加操作,并将结果打印到控制台上。代码如下:
#include
using namespace std;
int main(int argc, const char*artv[])
{
int x, y;
cout<<"input x:"<< endl;
cin>> x;
cout<<"input y:"<< endl;
cin>> y;
cout<< x<<"+"<< y<<"="<< x+ y<< endl;
return 0;
}
supprocess模块提供了一些函数,方便我们用于创建进程。
subprocess.call(*popenargs,**kwargs)
运行命令。该函数将一直等待到子进程运行结束,并返回进程的returncode。文章一开始的例子就演示了call函数。如果子进程不需要进行交互,就可以使用该函数来创建。
subprocess.check_call(*popenargs,**kwargs)
与subprocess.call(*popenargs,**kwargs)功能一样,只是如果子进程返回的returncode不为0的话,将触发CalledProcessError异常。在异常对象中,包括进程的returncode信息。
OK,本文到此结束,希望对大家有所帮助。