python中的subprocess.Popen() 执行shell命令

摘要:
subprocess介绍需要用到Python来执行shell脚本,因此需要查看下subprocess模块文档。subprocess模块的常用方法用法介绍subprocess.run()--˃python3.5中新增的函数,执行指定的命令,等待命令执行完成后返回一个包含执行结果的CompletedProcess类的实例。在python3.5之前的版本中,我们可以通过subprocess.call()来使用subprocess模块的功能。subprocess.run(),subprocess.call(),subprocess.check_call()都是通过对subprocess.Popen的封装来实现的高级函数。subprocess模块中只定义了一个类:Popen。subprocess.Popensubprocess.Popen这两个之中,后者将不会工作。
subprocess介绍

需要用到Python来执行shell脚本, 因此需要查看下subprocess模块文档。

根据官网文档描述:subprocess模块用于创建子进程, 这个模块用于替换旧版本中的一些模块, 如:os.system,

os.spawn*, os.popen*, os.popen*, popen2.*, commands.*, subprocess允许你能创建很多子进程, 创建的时候能能指定子进程和子进程的输入、输出、错误输出管道, 执行后能获取输出结果和执行状态。

subprocess模块的常用方法用法介绍

subprocess.run() --> python3.5中新增的函数, 执行指定的命令, 等待命令执行完成后返回一个包含执行结果的 CompletedProcess类的实例。

subprocess.call(): --> 执行指定的命令, 返回命令执行状态, 功能类似羽os.system(cmd)

subprocess.check_call(): --> python2.5中新增的函数, 执行指定的命令, 如果执行成功则返回状态码, 否则抛出异常。

【Tips】: 在python3.5之后的版本中, 官方文档中提倡通过subprocess.run()函数替代其他函数来使用subprocess模块的功能。在python3.5之前的版本中, 我们可以通过subprocess.call()来使用subprocess模块的功能。subprocess.run(), subprocess.call(), subprocess.check_call()都是通过对subprocess.Popen的封装来实现的高级函数。

###

三. 这几个函数的定义以及参数

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, universal_newlines=False)

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)

subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)
参数说明:

args: 要执行的shell命令, 默认应该是一个字符串序列, 如['ls', '-l'], 也可以是一个字符串如: 'ls -l', 但是此时需要把shell参数的值置为True。

【Tips】--> shell=True参数会让subprocess.call接受字符串类型的变量作为命令, 并调用shell去执行这个字符串, 当shell=False时, subprocess.call只接受数组变量作为命令, 并将数组的第一个元素作为命令, 剩下的全部作为该命令的参数。官方不推荐使用shell=True。

p = subprocess.run(["pwd"])
#p1 = subprocess.run(["cd"])#p2 = subprocess.run(["ls", "-l"])
print(p)

###

python中的subprocess.Popen() 执行shell命令第1张

###

subprocess.Popen

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

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

classsubprocess.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

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

subprocess.Popen(["cat","test.txt"])
subprocess.Popen("cat test.txt")
这两个之中,后者将不会工作。因为如果是一个字符串的话,必须是程序的路径才可以。(考虑unix的api函数exec,接受的是字符串
列表)
但是下面的可以工作
subprocess.Popen("cat test.txt", shell=True)
这是因为它相当于
subprocess.Popen(["/bin/sh", "-c", "cat test.txt"])
在*nix下,当shell=False(默认)时,Popen使用os.execvp()来执行子程序。args一般要是一个【列表】。如果args是个字符串的
话,会被当做是可执行文件的路径,这样就不能传入任何参数了。

注意:
shlex.split()可以被用于序列化复杂的命令参数,比如:

>>> shlex.split('ls ps top grep pkill')
['ls', 'ps', 'top', 'grep', 'pkill']
>>>importshlex, subprocess
>>>command_line =raw_input()
/bin/cat -input test.txt -output "diege.txt" -cmd "echo '$MONEY'" 
>>>args =shlex.split(command_line)
>>> printargs
['/bin/cat', '-input', 'test.txt', '-output', 'diege.txt', '-cmd', "echo '$MONEY'"]
>>>p=subprocess.Popen(args)

###

可以看到,空格分隔的选项(如-input)和参数(如test.txt)会被分割为列表里独立的项,但引号里的或者转义过的空格不在此列
。这也有点像大多数shell的行为。

在*nix下,当shell=True时,如果arg是个字符串,就使用shell来解释执行这个字符串。如果args是个列表,则第一项被视为命令,
其余的都视为是给shell本身的参数。也就是说,等效于:
subprocess.Popen(['/bin/sh', '-c', args[0], args[1], ...])

####

参数bufsize

参数bufsize一般0 无缓冲,1 行缓冲,其他正值 缓冲区大小,负值 采用默认系统缓冲(一般是全缓冲)

###

参数executable

executable一般不用,args字符串或列表第一项表示程序名

###

参数stdin, stdout, stderr

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

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

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

###

参数shell

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

####

参数env

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

###

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.pid
获取子进程的进程ID。

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

###

进程通信:

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

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

###

importsubprocess
p = subprocess.Popen("ls", shell=True, stdout=subprocess.PIPE)
(stdoutput, erroutput) =p.communicate()
print(stdoutput)
print(erroutput)

####

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

python中的subprocess.Popen() 执行shell命令第2张

上面的例子通过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()  
    if buff == '' and p.poll() !=None:  
        break 

死锁

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

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

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

subprocess还可以连接起来多个命令来执行。
在shell中我们知道,想要连接多个命令可以使用管道。
在subprocess中,可以使用上一个命令执行的输出结果作为下一次执行的输入。例子如下:

python中的subprocess.Popen() 执行shell命令第3张

####
#####

免责声明:文章转载自《python中的subprocess.Popen() 执行shell命令》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇正常人一天该走六千还是一万步?步数滚蛋,运动强度和时长才重要,锻炼身体,快走springboot-logback下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python编程系列---进程池的优越性体验

1.通过multiprocessing.Process()类创建子进程 1 import multiprocessing, time, os, random 2 3 4 def work(index): 5 """ 6 任务 7 :param index:任务索引号 8 """ 9 start_...

python文件和目录操作方法大全

一、python中对文件、文件夹操作时经常用到的os模块和shutil模块常用方法。1.得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd()2.返回指定目录下的所有文件和目录名:os.listdir()3.函数用来删除一个文件:os.remove()4.删除多个目录:os.removedirs(r“c:python”)5.检验给...

Python股票历史数据的获取

获取股票数据的接口很多,免费的接口有新浪、网易、雅虎的API接口,收费的就是证券公司及相应的公司提供的接口。收费试用的接口一般提供的数据只是最近一年或三年的,限制比较多,除非money足够多。所以本文主要讨论的是免费数据的获取及处理。 国内提供股票数据的接口如sinajs,money.163.com,yahoo,它们提供的API接口不同,每家提供的数据大同...

shell 检查文件夹所属用户组

shell 检查文件夹所属用户组 #!/bin/bash # 检查文件夹 权限是否777 检查文件夹所属组是否www # authro ranmufei # 2017 08 21 云板容器版 /data 目录权限判断 定时任务检查 cd / path=/data q=$(ls -l ${path}|sed -n '2p' |awk -F " " '{...

Python 练习题

python 练习题 day1 1.简述变量命名规范 7条: 1.由字母,数字和下划线组成 2.name = input(“>>>”) name变量是什么数据类型通过代码检测 type 3.if条件语句的基本结构? if 条件 : print() 4.用print打印出下面内容: ⽂能提笔安天下,武能上⻢定乾坤.⼼存谋略何⼈胜,...

哪种脚本语言最适合你!

本文译自 iSystemAdmin 的 《List Of Popular Scripting Languages for Linux and Windows》。 具备脚本知识的系统管理员与其他系统管理员有着明显的区别。脚本是一门“系统管理员”创造的艺术。这门艺术需要了解系统本身的相关知识,系统管理命令的语法,编程和算法知识以及至少一门脚本编程语言。对系统管...