燕十八html教程网站建设,公司可以做网站吗,长春专业做网站公司排名,宁波专业做网站的公司从python2.4版本开始,可以用subprocess这个模块来产生子进程,并连接到子进程的标准输入/输出/错误中去#xff0c;还可以得到子进程的返回值。subprocess意在替代其他几个老的模块或者函数#xff0c;比如#xff1a;os.system os.spawn* os.popen* popen2.* commands.*一、…从python2.4版本开始,可以用subprocess这个模块来产生子进程,并连接到子进程的标准输入/输出/错误中去还可以得到子进程的返回值。subprocess意在替代其他几个老的模块或者函数比如os.system os.spawn* os.popen* popen2.* commands.*一、subprocess.Popensubprocess模块定义了一个类 Popenclass subprocess.Popen( args,bufsize0,executableNone,stdinNone,stdoutNone,stderrNone,preexec_fnNone,close_fdsFalse,shellFalse,cwdNone,envNone,universal_newlinesFalse,startupinfoNone,creationflags0)各参数含义如下args:args参数。可以是一个字符串可以是一个包含程序参数的列表。要执行的程序一般就是这个列表的第一项或者是字符串本身。subprocess.Popen([cat,test.txt])subprocess.Popen(cat test.txt)这两个之中后者将不会工作。因为如果是一个字符串的话必须是程序的路径才可以。(考虑unix的api函数exec接受的是字符串列表)但是下面的可以工作subprocess.Popen(cat test.txt, shellTrue)这是因为它相当于subprocess.Popen([/bin/sh, -c, cat test.txt])在*nix下当shellFalse(默认)时Popen使用os.execvp()来执行子程序。args一般要是一个【列表】。如果args是个字符串的话会被当做是可执行文件的路径这样就不能传入任何参数了。注意shlex.split()可以被用于序列化复杂的命令参数比如 shlex.split(ls ps top grep pkill)[ls, ps, top, grep, pkill]import shlex, subprocesscommand_line raw_input()/bin/cat -input test.txt -output diege.txt -cmd echo $MONEYargs shlex.split(command_line) print args[/bin/cat, -input, test.txt, -output, diege.txt, -cmd, echo $MONEY]psubprocess.Popen(args)可以看到空格分隔的选项(如-input)和参数(如test.txt)会被分割为列表里独立的项但引号里的或者转义过的空格不在此列。这也有点像大多数shell的行为。在*nix下当shellTrue时如果arg是个字符串就使用shell来解释执行这个字符串。如果args是个列表则第一项被视为命令其余的都视为是给shell本身的参数。也就是说等效于subprocess.Popen([/bin/sh, -c, args[0], args[1], ...])在Windows下下面的却又是可以工作的subprocess.Popen([notepad.exe, test.txt])subprocess.Popen(notepad.exe test.txt)这是由于windows下的api函数CreateProcess接受的是一个字符串。即使是列表形式的参数也需要先合并成字符串再传递给api函数subprocess.Popen(notepad.exe test.txt shellTrue)等同于subprocess.Popen(cmd.exe /C notepad.exe test.txt shellTrue)bufsize参数:如果指定了bufsize参数作用就和内建函数open()一样0表示不缓冲1表示行缓冲其他正数表示近似的缓冲区字节数负数表示使用系统默认值。默认是0。executable参数:指定要执行的程序。它很少会被用到一般程序可以由args 参数指定。如果shellTrue executable可以用于指定用哪个shell来执行(比如bash、csh、zsh等)。*nix下默认是 /bin/sh windows下就是环境变量 COMSPEC的值。windows下只有当你要执行的命令确实是shell内建命令(比如dir copy 等)时你才需要指定shellTrue而当你要执行一个基于命令行的批处理脚本的时候不需要指定此项。stdin stdout和stderrstdin stdout和stderr分别表示子程序的标准输入、标准输出和标准错误。可选的值有PIPE或者一个有效的文件描述符(其实是个正整数)或者一个文件对象还有None。如果是PIPE则表示需要创建一个新的管道如果是None不会做任何重定向工作子进程的文件描述符会继承父进程的。另外stderr的值还可以是STDOUT表示子进程的标准错误也输出到标准输出。preexec_fn参数如果把preexec_fn设置为一个可调用的对象(比如函数)就会在子进程被执行前被调用。(仅限*nix)close_fds参数如果把close_fds设置成True*nix下会在开子进程前把除了0、1、2以外的文件描述符都先关闭。在 Windows下也不会继承其他文件描述符。shell参数如果把shell设置成True指定的命令会在shell里解释执行。cwd参数如果cwd不是None则会把cwd做为子程序的当前目录。注意并不会把该目录做为可执行文件的搜索目录所以不要把程序文件所在目录设置为cwd 。env参数如果env不是None则子程序的环境变量由env的值来设置而不是默认那样继承父进程的环境变量。注意即使你只在env里定义了某一个环境变量的值也会阻止子程序得到其他的父进程的环境变量(也就是说如果env里只有1项那么子进程的环境变量就只有1个了)。例如 subprocess.Popen(env, env{test:123, testtext:zzz})test123testtextzzzuniversal_newlines参数:如果把universal_newlines 设置成True则子进程的stdout和stderr被视为文本对象并且不管是*nix的行结束符(/n)还是老mac格式的行结束符(/r )还是windows 格式的行结束符(/r/n )都将被视为 /n 。startupinfo和creationflags参数如果指定了startupinfo和creationflags将会被传递给后面的CreateProcess()函数用于指定子程序的各种其他属性比如主窗口样式或者是子进程的优先级等。(仅限Windows)二、subprocess.PIPEsubprocess.PIPE一个可以被用于Popen的stdin 、stdout 和stderr 3个参数的特输值表示需要创建一个新的管道。subprocess.STDOUT一个可以被用于Popen的stderr参数的输出值表示子程序的标准错误汇合到标准输出。实例psubprocess.Popen(df -h,shellTrue,stdoutsubprocess.PIPE)outp.stdout.readlines()out[bFilesystem Size Used Avail Capacity Mounted on\n, b/dev/ad0s1a 713M 313M 343M 48% /\n, bdevfs 1.0K 1.0K 0B 100% /dev\n, b/dev/ad0s1e 514M 2.1M 471M 0% /tmp\n, b/dev/ad0s1f 4.3G 2.5G 1.4G 64% /usr\n, b/dev/ad0s1d 2.0G 121M 1.7G 6% /var\n for line in out:... print line.strip()...Filesystem Size Used Avail Capacity Mounted on/dev/ad0s1a 713M 313M 343M 48% /devfs 1.0K 1.0K 0B 100% /dev/dev/ad0s1e 514M 2.1M 471M 0% /tmp/dev/ad0s1f 4.3G 2.5G 1.4G 64% /usr/dev/ad0s1d 2.0G 121M 1.7G 6% /varstdout可以使用read(),readline(),readlines()等方法三、方便的函数1、subprocess.callsubprocess.call (*popenargs , **kwargs )执行命令并等待命令结束再返回子进程的返回值。参数同Popen查看/usr/lib/python2.7/subprocess.py去掉文档其实是这样的def call(*popenargs, **kwargs):return Popen(*popenargs, **kwargs).wait() subprocess.call(ifconfig,shellTrue)2、subprocess.check_callsubprocess.check_call (*popenargs , **kwargs )执行上面的call命令并检查返回值如果子进程返回非0则会抛出CalledProcessError异常这个异常会有个returncode属性记录子进程的返回值。def check_call(*popenargs, **kwargs):retcode call(*popenargs, **kwargs)if retcode:cmd kwargs.get(args)raise CalledProcessError(retcode, cmd)return 0 subprocess.check_call(ifconfig) subprocess.call(noifconfig)Traceback (most recent call last):File , line 1, in File /usr/local/lib/python2.7/subprocess.py, line 493, in callreturn Popen(*popenargs, **kwargs).wait()File /usr/local/lib/python2.7/subprocess.py, line 679, in __init__errread, errwrite)File /usr/local/lib/python2.7/subprocess.py, line 1228, in _execute_childraise child_exceptionOSError: [Errno 2] No such file or directory异常子进程里抛出的异常会在父进程中再次抛出。并且异常会有个叫child_traceback的额外属性这是个包含子进程错误traceback信息的字符串。遇到最多的错误回是 OSError比如执行了一个并不存在的子程序就会产生OSError。另外如果使用错误的参数调用Popen会抛出ValueError。当子程序返回非0时check_call()还会产生CalledProcessError 异常。安全性不像其他的popen函数本函数不会调用/bin/sh来解释命令也就是说命令中的每一个字符都会被安全地传递到子进程里。3、check_outputcheck_output()执行程序并返回其标准输出.def check_output(*popenargs, **kwargs):process Popen(*popenargs, stdoutPIPE, **kwargs)output, unused_err process.communicate()retcode process.poll()if retcode:cmd kwargs.get(args)raise CalledProcessError(retcode, cmd, outputoutput)return outputpsubprocess.check_output(ifconfig)结果是所有行/n分割的一个字符串可以直接print出来这里开始4、Popen对象产生对象psubprocess.Popen(df -h,shellTrue,stdoutsubprocess.PIPE) dir(p)Popen对象有以下方法Popen.poll()检查子进程是否已结束设置并返回returncode属性。 p.poll()0Popen.wait()等待子进程结束设置并返回returncode属性。 p.wait()0注意 如果子进程输出了大量数据到stdout或者stderr的管道并达到了系统pipe的缓存大小的话子进程会等待父进程读取管道而父进程此时正wait着的话将会产生传说中的死锁后果是非常严重滴。建议使用communicate() 来避免这种情况的发生。Popen.communicate(inputNone)和子进程交互发送数据到stdin并从stdout和stderr读数据直到收到EOF。等待子进程结束。可选的input如有有的话要为字符串类型。此函数返回一个元组 (stdoutdata , stderrdata ) 。注意要给子进程的stdin发送数据则Popen的时候stdin要为PIPE同理要可以接收数据的话stdout或者stderr也要为PIPE。p1subprocess.Popen(cat /etc/passwd,shellTrue,stdinsubprocess.PIPE,stdoutsubprocess.PIPE) p2subprocess.Popen(grep 0:0,shellTrue,stdinp1.stdout,stdoutsubprocess.PIPE)注意读到的数据会被缓存在内存里所以数据量非常大的时候要小心了。 p.communicate()(bFilesystem Size Used Avail Capacity Mounted on\n/dev/ad0s1a 713M 313M 343M 48% /\ndevfs 1.0K 1.0K 0B 100% /dev\n/dev/ad0s1e 514M 2.1M 471M 0% /tmp\n/dev/ad0s1f 4.3G 2.5G 1.4G 64% /usr\n/dev/ad0s1d 2.0G 121M 1.7G 6% /var\n, None)Popen.send_signal(signal)给子进程发送signal信号。注意windows下目前只支持发送SIGTERM等效于下面的terminate() 。Popen.terminate()停止子进程。Posix下是发送SIGTERM信号。windows下是调用TerminateProcess()这个API。Popen.kill()杀死子进程。Posix下是发送SIGKILL信号。windows下和terminate() 无异。Popen.stdin如果stdin 参数是PIPE此属性就是一个文件对象否则为None 。Popen.stdout如果stdout参数是PIPE此属性就是一个文件对象否则为None 。Popen.stderr如果stderr 参数是PIPE此属性就是一个文件对象否则为None 。Popen.pid子进程的进程号。注意如果shell 参数为True这属性指的是子shell的进程号。 p.pid22303Popen.returncode子程序的返回值由poll()或者wait()设置间接地也由communicate()设置。如果为None表示子进程还没终止。如果为负数-N的话表示子进程被N号信号终止。(仅限*nux)用subprocess来代替其他函数都可以用subprocess来完成我们假定是用 “from subprocess import *” 来导入模块的代替shell命令pls -l等效于pPopen([ls,-l],stdoutPIPE).communicate()[0]代替shell管道pdmesg | grep cpu等效于p1Popen([dmesg],stdoutPIPE)p2Popen([grep,cpu],stdinp1.stdout,stdoutPIPE)output p2.communicate()[0]outputcpu0: on acpi0\nacpi_throttle0: on cpu0\n p1subprocess.Popen(cat /etc/passwd,shellTrue,stdoutsubprocess.PIPE) p2subprocess.Popen(grep 0:0,shellTrue,stdinp1.stdout,stdoutsubprocess.PIPE) p3subprocess.Popen(cut -d : -f 7,shellTrue,stdinp2.stdout,stdoutsubprocess.PIPE) print p3.stdout.read()代替os.system()lsl os.system(ls -l)这个是一个返回状态等效于pPopen(ls -l, shellTrue)lslos.waitpid(p.pid,0)[1]注意通常并不需要用shell来调用程序。用subprocess可以更方便地得到子程序的返回值。其实更真实的替换是try:retcode call(“mycmd” ” myarg”, shellTrue)if retcode 0:print sys.stderr, “Child was terminated by signal”, -retcodeelse:print sys.stderr, “Child returned”, retcodeexcept OSError, e:print sys.stderr, “Execution failed:”, e代替os.spawn系列P_NOWAIT的例子pid os.spawnlp(os.P_NOWAIT, “/bin/mycmd”, “mycmd”, “myarg”)等效于pid Popen([/bin/mycmd, myarg]).pidP_WAIT的例子retcode os.spawnlp(os.P_WAIT, “/bin/mycmd”, “mycmd”, “myarg”)等效于retcode call([/bin/mycmd, myarg])返回值处理pipe os.popen(“cmd”, ‘w’)...rc pipe.close()if rc ! None and rc % 256:print “There were some errors”等效于process Popen(“cmd”, ‘w’, shellTrue, stdinPIPE)...process.stdin.close()if process.wait() ! 0:print “There were some errors”