python subprocess_python subprocess stdout utf8-程序员宅基地

技术标签: pthon学习  

subprocess – 创建附加进程 
subprocess模块提供了一种一致的方法来创建和处理附加进程,与标准库中的其它模块相比,提供了一个更高级的接口。用于替换如下模块: 

os.system() , os.spawnv() , os和popen2模块中的popen()函数,以及 commands().

subprocess模块,替换os.system等

subprocess.run(['df','-h']) 当参数传,Python解析,如果有管道符就不行了
subprocess.run('df -h | grep sda1', shell=True) shell=True是指不需要Python解析,直接把字符串给shell
Python3.5才出现subprocess.run
终端输入的命令分为两种:
输入即可得到输出,如:ifconfig
输入进行某环境,依赖再输入,如:Python

常用subprocess

没有管道 
retcode = subprocess.call(['ls','-l']) 成功返回0,不成功返回非0
subprocess.check_call(['ls','-l']) 执行成功返回0,执行错误抛异常
subprocess.getoutput('ls /bin/ls')接收字符串格式命令,只返回结果
res = subprocess.check_output(['ls','-l'])执行成功返回执行结果,不成功出错
subprocess.getstatsoutput('ls /bin/ls') 返回元祖(1,'/bin/ls'),第一个状态,第二个结果

上面的方法,底层都是封装subprocess.popen
例子
res = subprocess.popen('ifconfig | grep 192',shell=True)
res
<subprocess.popen object at ox7f2131a>
res.stdout.read()读不出来
要读出来要先输出到标准输出里,先存到管道PIPE 再给stdout python和shell是两个进程不能独立通信,必须通过操作系统提供的管道
用管道可以把结果存到stdin stdout stderr
subprocess.popen('ifconfig | grep 192',shell=True,stdout=subprocess.PIPE)
res.stdout.read()就可以读出来了
subprocess.popen('ifconfig | gr1111ep 192',shell=True,stdout=subprocess.PIPE)
出错会直接打印错误。想不打印错误可以stderr保存stderr=subprocess.PIPE


poll() check if child process has terminated. returns returncode
---------
res=subprocess.popen("sleep 10;echo 'hello'", shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
执行的时候没反应,不知道是卡主了还是执行完了
每次调subprocess执行Linux命令,都相当于启动了一个新的shell,启动新的进程,执行一次命令等结果
如果该命令要花半小时,不知道是卡主了还是执行完了,可以res.poll()返回none表示还没有执行完,返回0表示执行完了
res.wait()等待结束然后返回0
----------
terminate()杀掉该进程,res.terminate()
wait() wait for child process to terminate. returns returncode attribute
communicate()等待任务结束 没什么用,用Python当参数,输Python进入环境
stdin 标准输入
stdout 标准输出
stderr 标准错误
pid the process ID of the child process


-----可用参数
args: shell命令,可以是字符串或者序列类型
bufsize:指定缓冲,0无缓冲,1 行缓冲,其他 缓冲区大小 负值 系统缓冲
stdin,stdout,stderr:标准输入,输出,错误句柄
preexec_fn:只在Unix平台下有效,用于指定一个可执行对象,它将在子进程运行之前被调用
close_sfs:在Windows平台下,如果close_sfs被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道
所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误

shell:同上
cod:用于设置子进程的当前目录
env:用于指定子进程的环境变量。如果env=None,子进程的环境变量将从父进程中继承
universal_newlines:不同系统的换行符不同,True->同意使用\n
startupinfo与createionflags只在Windows下有效
将被传递给底层的createprocess()函数,用于设置子进程的一些属性,
如:主窗口的外观,进程的优先级等


subprocess实现sudo自动输入密码
例如Python里面执行sudo apt-get install vim (Linux里面要输入密码)
linux中应该echo '123' | sudo -S iptables -L
python直接 subprocess.popen("echo '123' | sudo -S iptables -L",shell=True)


1. 运行外部命令 
subprocess.call(command) 方法 
subprocess的call方法可以用于执行一个外部命令,但该方法不能返回执行的结果,只能返回执行的状态码: 成功(0) 或 错误(非0) 
call()方法中的command可以是一个列表,也可以是一个字符串,作为字符串时需要用原生的shell来执行:

import subprocess
#执行 df -hl 命令
#方法1:
>>> subprocess.call(['ls','-l'])
total 8
drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem
drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp
0
#方法2:
>>> subprocess.call("ls -l",shell=True)
total 8
drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem
drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp
0
  • 如上实例所示,虽然我们能看到执行的结果,但实际获取的值只是状态码
>>> output = subprocess.call("ls -l",shell=True)
total 8
drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem
drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp
>>> print(output)
0

2. 错误处理 
subprocess.check_call() 方法 
我们说过call执行返回一个状态码,我们可以通过check_call()函数来检测命令的执行结果,如果不成功将返回 subprocess.CalledProcessError 异常

>>> try:
        subprocess.check_call("ls -t", shell=True)
    except subprocess.CalledProcessError as err:
        print("Command Error") 

/bin/sh: lt: command not found
Command Error

3. 捕获输出结果 
subprocess.check_output() 方法

call()方法启动的进程,其标准输入输出会绑定到父进程的输入和输出。调用程序无法获取命令的输出结果。但可以通过check_output()方法来捕获输出。

# 以下测试为python3.4下运行结果
>>> output=subprocess.check_output("ls -l",shell=True)
>>> output
b'total 8\ndrwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem\ndrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp\n'
>>> print(output.decode('utf-8'))
total 8
drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem
drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp
  • 以下例子将chek_output()方法执行命令异常时的错误捕获,而避免输出到控制台.
try:
    output = subprocess.check_output("lT -l", shell=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as err:
    print("Command Error", err)

# 执行结果
Command Error Command 'lT -l' returned non-zero exit status 127
  • 直接处理管道 

subprocess.Popen()方法

函数call(), check_call() 和 check_output() 都是Popen类的包装器。直接使用Popen会对如何运行命令以及如何处理其输入输出有更多控制。如通过为stdin, stdout和stderr传递不同的参数。

  1. 与进程的单向通信 
    通过Popen()方法调用命令后执行的结果,可以设置stdout值为PIPE,再调用communicate()获取结果 
    返回结果为tuple. 在python3中结果为byte类型,要得到str类型需要decode转换一下

输出结果(读)

# 直接执行命令输出到屏幕
>>> subprocess.Popen("ls -l",shell=True)
<subprocess.Popen object at 0x7febd4175198>
>>> total 12
drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem
-rw-rw-r-- 1 ws ws    8 Feb 25 10:38 test
drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp

# 不输出到屏幕,输出到变量
>>> proc = subprocess.Popen(['echo','"Stdout"'],stdout=subprocess.PIPE)
# communicate返回标准输出或标准出错信息
>>> stdout_value = proc.communicate()
>>> stdout_value
(b'"Stdout"\n', None)

>>> proc = subprocess.Popen(['ls','-l'],stdout=subprocess.PIPE)
>>> stdout_value = proc.communicate()
>>> stdout_value
(b'total 8\ndrwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem\ndrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp\n', None)
>>>
>>> print((stdout_value[0]).decode('utf-8'))
total 8
drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem
drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp

#将结果输出到文件
>>> file_handle = open("/home/ws/t.log",'w+')
>>> subprocess.Popen("ls -l",shell=True,stdout=file_handle)
t.log:
drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem
-rw-rw-r-- 1 ws ws    8 Feb 25 10:38 test
-rw-rw-r-- 1 ws ws    0 Feb 25 11:24 t.log
drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp

2 与进程的双向通信

>>> proc = subprocess.Popen('cat', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>> msg = 'Hello world'.encode('utf-8')
# 写入到输入管道
>>> proc.stdin.write(msg)
11
>>> stdout_value = proc.communicate()
>>> stdout_value
(b'Hello world', None)

# 在需要进行相互交互的输入输出过程也可以使用shtin来实现
# 以下实现打开python3的终端,执行一个print命令
>>>proc = subprocess.Popen(['python3'],stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE,)
>>>proc.stdin.write('print("helloworld")'.encode('utf-8'))
>>>out_value,err_value=proc.communicate()
>>>print(out_value)
>>> print(out_value)
b'helloworld\n'
>>> print(err_value)
b''
  • Popen.communicate()方法用于和子进程交互:发送数据到stdin,并从stdout和stderr读数据,直到收到EOF。等待子进程结束。

捕获错误输出

>>> proc = subprocess.Popen(['python3'],stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE,)
>>> proc.stdin.write('print "helloworld"'.encode('utf-8'))
18
>>> out_value,err_value=proc.communicate()
>>> out_value
b''
>>> print(err_value.decode('utf-8'))
  File "<stdin>", line 1
    print "helloworld"
                     ^
SyntaxError: Missing parentheses in call to 'print'

Popen其它方法

  1. Popen.pid 查看子进程ID
  2. Popen.returncode 获取子进程状态码,0表示子进程结束,None未结束

    在使用Popen调用系统命令式,建议使用communicate与stdin进行交互并获取输出(stdout),这样能保证子进程正常退出而避免出现僵尸进程。看下面例子

>>> proc = subprocess.Popen('ls -l', shell=True, stdout=subprocess.PIPE)
# 当前子进程ID
>>> proc.pid
28906
# 返回状态为None,进程未结束
>>> print(proc.returncode)
None
# 通过communicate提交后
>>> out_value = proc.communicate()
>>> proc.pid
28906
# 返回状态为0,子进程自动结束
>>> print(proc.returncode)
0
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_33932782/article/details/79865244

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf