python利用subprocess执行交互命令
已经知道,os.system可以方便的利用python代码执行一些像ping、ipconfig之类的系统命令,但却只能得到命令执行是否成功,不能获得命令成功执行后的结果,像下面这样:
>>> s = os.system("ping www.baidu.com") 正在 Ping www.a.shifen.com [220.181.38.150] 具有 32 字节的数据:
来自 220.181.38.150 的回复: 字节=32 时间=18ms TTL=52
来自 220.181.38.150 的回复: 字节=32 时间=19ms TTL=52
来自 220.181.38.150 的回复: 字节=32 时间=23ms TTL=52
来自 220.181.38.150 的回复: 字节=32 时间=22ms TTL=52 220.181.38.150 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 18ms,最长 = 23ms,平均 = 20ms
>>> s
0
>>> type(s)
<class 'int'>
>>>
在上面的代码中,利用os.system执行“ping www.baidu.com”并把结果赋值给s,但在下面可以看到,s的内容是int类型的0(表示命令执行成功),并不是命令的执行结果。如果只是需要判断命令是否执行成功,那完全可以使用这种方法,但如果想要获取命令执行的结果呢?可以使用subprocess这个模块。
一:subprocess的作用
subprocess模块主要用于创建子进程,并连接它们的输入、输出和错误管道,获取它们的返回状态。通俗地说就是通过这个模块,你可以在Python的代码里执行操作系统级别的命令,比如“ipconfig”、“du -sh”等等。subprocess模块替代了一些老的模块和函数,比如:
os.system
os.spawn*
subprocess过去版本中的call()
,check_call()
和check_output()
已经被run()
方法取代了。run()
方法为3.5版本新增。大多数情况下,推荐使用run()
方法调用子进程,执行操作系统命令。在更高级的使用场景,你还可以使用Popen接口。其实run()
方法在底层调用的就是Popen接口。
二:subprocess的run方法
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, encoding=None, errors=None)
功能:执行args参数所表示的命令,等待命令结束,并返回一个CompletedProcess类型对象。
下面是run参数的作用:
args:表示要执行的命令。必须是一个字符串,字符串参数列表。 stdin、stdout和stderr:子进程的标准输入、输出和错误。其值可以是subprocess.PIPE、subprocess.DEVNULL、一个已经存在的文件描述符、已经打开的文件对象或者None。subprocess.PIPE表示为子进程创建新的管道。subprocess.DEVNULL表示使用os.devnull。默认使用的是None,表示什么都不做。另外,stderr可以合并到stdout里一起输出。 timeout:设置命令超时时间。如果命令执行时间超时,子进程将被杀死,并弹出TimeoutExpired异常。 check:如果该参数设置为True,并且进程退出状态码不是0,则弹出CalledProcessError异常。 encoding:如果指定了该参数,则stdin、stdout和stderr可以接收字符串数据,并以该编码方式编码。否则只接收bytes类型的数据。 shell:如果该参数为True,将通过操作系统的shell执行指定的命令,如果执行命令时遇见权限不足的境况,可以将此参数设置为True
注意,run()方法返回的不是我们想要的执行结果或相关信息,而是一个CompletedProcess类型对象。
>>> r = subprocess.run("ping www.baidu.com") 正在 Ping www.a.shifen.com [220.181.38.150] 具有 32 字节的数据:
来自 220.181.38.150 的回复: 字节=32 时间=17ms TTL=52
来自 220.181.38.150 的回复: 字节=32 时间=17ms TTL=52
来自 220.181.38.150 的回复: 字节=32 时间=19ms TTL=52
来自 220.181.38.150 的回复: 字节=32 时间=18ms TTL=52 220.181.38.150 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 17ms,最长 = 19ms,平均 = 17ms
>>> type(r)
<class 'subprocess.CompletedProcess'>
>>> r
CompletedProcess(args='ping www.baidu.com', returncode=0)
>>>
可以看到,run方法的执行结果是一个CompletedProcess类型对象。
下面是CompletedProcess类型对象的一些属性:
args 启动进程的参数,通常是个列表或字符串。 returncode 进程结束状态返回码。0表示成功状态。 stdout 获取子进程的stdout。通常为bytes类型序列,None表示没有捕获值。如果你在调用run()方法时,设置了参数stderr=subprocess.STDOUT,则错误信息会和stdout一起输出,此时stderr的值是None。 stderr() 获取子进程的错误信息。通常为bytes类型序列,None表示没有捕获值。 check_returncode() 用于检查返回码。如果返回状态码不为零,弹出CalledProcessError异常。
获取状态码:
r = subprocess.run("ping www.baidu.com") 正在 Ping www.a.shifen.com [220.181.38.150] 具有 32 字节的数据:
来自 220.181.38.150 的回复: 字节=32 时间=35ms TTL=52
来自 220.181.38.150 的回复: 字节=32 时间=29ms TTL=52
来自 220.181.38.150 的回复: 字节=32 时间=16ms TTL=52
来自 220.181.38.150 的回复: 字节=32 时间=18ms TTL=52 220.181.38.150 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 16ms,最长 = 35ms,平均 = 24ms>>> r.returncode
0
获取命令执行后的内容:
run()方法返回的是一个CompletedProcess类型对象,不能直接获取我们通常想要的结果。要获取命令执行的结果或者信息,在调用run()方法的时候,请指定stdout=subprocess.PIPE。
>>> ret = subprocess.run('dir', shell=True, stdout=subprocess.PIPE)
>>> ret
CompletedProcess(args='dir', returncode=0, stdout=b' \xc7\xfd\xb6\xaf\xc6\xf7 C \xd6\xd0\xb5\xc4\xbe\xed\xca\xc7 Windows 10\r\n \xbe\xed\xb5\xc4\xd0\xf2\xc1\xd0\xba\xc5\xca\xc7 02DE-BFF0\r\n\r\n C:\\Users\\lwy \xb5\xc4\xc4\xbf\xc2\xbc\r\n\r\n2019/12/31 10:29 <DIR> .\r\n2019/12/31 10:29 <DIR> ..\r\n2019/10/16 10:27 <DIR> .3T\r\n2019/09/23 20:31 <DIR> .anaconda\r\n2019/10/07 13:14 <DIR> .android\r\n2019/07/23 09:54 <DIR> .astropy\r\n2019/12/28 19:01 4,807 .bash_history\r\n2019/09/26 18:19 <DIR> .conda\r\n2019/09/26 18:19 151 .condarc\r\n2019/10/07 10:18 <DIR> .config\r\n2019/11/02 11:50 1,126 .dbshell\r\n2019/07/31 16:49 181 .gitconfig\r\n2019/07/22 20:31 <DIR> .ipython\r\n2019/09/23 16:15 <DIR> .keras\r\n2019/11/06 21:47 <DIR> .matplotlib\r\n2019/08/01 09:36 37 .minttyrc\r\n2019/10/06 20:53 <DIR> .mitmproxy\r\n2019/10/01 15:20 0 .mongorc.js\r\n2019/08/30 15:19 <DIR> .oracle_jre_usage\r\n2019/07/21 23:57 <DIR> .PyCharm2019.1\r\n2019/12/10 17:04 25 .python_history\r\n2019/07/31 16:04 <DIR> .rdm\r\n2019/07/31 16:38 35 .rediscli_history\r\n2019/07/22 20:31 <DIR> .spyder-py3\r\n2019/09/17 17:51 5,339 .viminfo\r\n2019/12/12 13:21 <DIR> 3D Objects\r\n2019/12/12 13:21 <DIR> Contacts\r\n2019/12/31 13:41 <DIR> Desktop\r\n2019/12/18 15:47 <DIR> Documents\r\n2019/12/30 16:34 <DIR> Downloads\r\n2019/12/12 13:21 <DIR> Favorites\r\n2019/10/15 16:36 <DIR> Funshion\r\n2019/12/12 13:21 <DIR> Links\r\n2019/12/12 13:21 <DIR> Music\r\n2019/07/21 23:58 <DIR> OneDrive\r\n2019/12/12 13:21 <DIR> Pictures\r\n2019/12/12 13:21 <DIR> Saved Games\r\n2019/12/12 13:21 <DIR> Searches\r\n2019/12/31 10:27 <DIR> test22\r\n2019/12/12 13:21 <DIR> Videos\r\n 9 \xb8\xf6\xce\xc4\xbc\xfe 11,701 \xd7\xd6\xbd\xda\r\n 31 \xb8\xf6\xc4\xbf\xc2\xbc 51,676,090,368 \xbf\xc9\xd3\xc3\xd7\xd6\xbd\xda\r\n')
>>> type(ret)
<class 'subprocess.CompletedProcess'>
>>>
可以看到,这时候返回的内容就是命令的执行结果了,是一个CompletedProcess的类型,也可以通过指定编码使返回对象是一个字符串类型。
>>> ret = subprocess.run('dir', shell=True, stdout=subprocess.PIPE).stdout.decode("gbk")
>>> ret
' 驱动器 C 中的卷是 Windows 10\r\n 卷的序列号是 02DE-BFF0\r\n\r\n C:\\Users\\lwy 的目录\r\n\r\n2019/12/31 10:29 <DIR> .\r\n2019/12/31 10:29 <DIR> ..\r\n2019/10/16 10:27 <DIR> .3T\r\n2019/09/23 20:31 <DIR> .anaconda\r\n2019/10/07 13:14 <DIR> .android\r\n2019/07/23 09:54 <DIR> .astropy\r\n2019/12/28 19:01 4,807 .bash_history\r\n2019/09/26 18:19 <DIR> .conda\r\n2019/09/26 18:19 151 .condarc\r\n2019/10/07 10:18 <DIR> .config\r\n2019/11/02 11:50 1,126 .dbshell\r\n2019/07/31 16:49 181 .gitconfig\r\n2019/07/22 20:31 <DIR> .ipython\r\n2019/09/23 16:15 <DIR> .keras\r\n2019/11/06 21:47 <DIR> .matplotlib\r\n2019/08/01 09:36 37 .minttyrc\r\n2019/10/06 20:53 <DIR> .mitmproxy\r\n2019/10/01 15:20 0 .mongorc.js\r\n2019/08/30 15:19 <DIR> .oracle_jre_usage\r\n2019/07/21 23:57 <DIR> .PyCharm2019.1\r\n2019/12/10 17:04 25 .python_history\r\n2019/07/31 16:04 <DIR> .rdm\r\n2019/07/31 16:38 35 .rediscli_history\r\n2019/07/22 20:31 <DIR> .spyder-py3\r\n2019/09/17 17:51 5,339 .viminfo\r\n2019/12/12 13:21 <DIR> 3D Objects\r\n2019/12/12 13:21 <DIR> Contacts\r\n2019/12/31 13:41 <DIR> Desktop\r\n2019/12/18 15:47 <DIR> Documents\r\n2019/12/30 16:34 <DIR> Downloads\r\n2019/12/12 13:21 <DIR> Favorites\r\n2019/10/15 16:36 <DIR> Funshion\r\n2019/12/12 13:21 <DIR> Links\r\n2019/12/12 13:21 <DIR> Music\r\n2019/07/21 23:58 <DIR> OneDrive\r\n2019/12/12 13:21 <DIR> Pictures\r\n2019/12/12 13:21 <DIR> Saved Games\r\n2019/12/12 13:21 <DIR> Searches\r\n2019/12/31 10:27 <DIR> test22\r\n2019/12/12 13:21 <DIR> Videos\r\n 9 个文件 11,701 字节\r\n 31 个目录 51,681,050,624 可用字节\r\n'
>>> type(ret)
<class 'str'>
>>>
三:subprocess的Popen方法
并不是所有的操作系统命令都像‘dir’或者‘ipconfig’那样单纯地返回执行结果,还有很多像‘python’这种交互式的命令,你要输入点什么,然后它返回执行的结果。subprocess中的Popen方法,可以执行一些交互性的命令。run方法也可以进行一些输入,不过很不方便,也不是以代码的形式驱动的,想要了解的同学可以看下文末大佬的原文。
Popen的用法和参数与run()方法基本类同,但是它的返回值是一个Popen对象,而不是CompletedProcess
对象。
>>> r = subprocess.Popen("dir", shell=True)>>> type(r)
<class 'subprocess.Popen'>
>>> r
<subprocess.Popen object at 0x000001921134EC48>
>>>
要‘python’命令功能,可以按下面的例子操作:
import subprocess s = subprocess.Popen("python", stdout=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
s.stdin.write(b"import os\n")
s.stdin.write(b"print(os.environ)")
s.stdin.close() out = s.stdout.read().decode("GBK")
s.stdout.close()
print(out)
另外,也可以把需要执行的后续命令卸载一个txt文件里,打开这个文件并赋值给stdin这个参数:
f = open("111.txt", "r+") s = subprocess.Popen("python",stdout=subprocess.PIPE, stdin=f, shell=True) out = s.stdout.read().decode("utf-8")
s.stdout.close()
print(out)
111.txt文件中的内容是:
import os
print(os.getcwd())
注意:每行代码后面要加换行。
参考文章:http://www.liujiangblog.com/course/python/55
********************不积跬步无以至千里********************
python利用subprocess执行交互命令的更多相关文章
- python 利用subprocess调用cmd命令程序,并正确输出控制台的输出中文
平台Python3.7 1.利用控制台运行程序后在控制台会输出中文提示,但是用python调用subprocess.run函数后返回的输出是乱码,于是,解决方法是用subprocess.check_o ...
- python利用paramiko执行服务器命令
话不多说直接上代码 封装连接 @staticmethod def connect(ip, server_user, server_port, server_path): ""&qu ...
- Python ssh 远程执行shell命令
工具 python paramiko 远程执行命令 import paramiko ssh = paramiko.SSHClient() key = paramiko.AutoAddPolicy() ...
- appium自动化测试框架——在python脚本中执行dos命令
一般我们运行dos命令,会有两种需求,一种是需要收集执行结果,如ip.device等:一种是不需要收集结果,如杀死或开启某个服务. 对应的在python中就要封装两种方法,来分别实现这两种需求. 1. ...
- Python教程:执行cmd命令
我们通常可以使用os模块的命令进行执行cmd 方法一:os.system def system(*args, **kwargs): # real signature unknown "&qu ...
- python中command执行shell命令脚本方法
在Python中有一个模块commands也很容易做到以上的效果.看一下三个函数:1). commands.getstatusoutput(cmd)用os.popen()执行命令cmd, 然后返回两个 ...
- Flex利用JavaScript执行cmd命令
Flex: //注册js事件 protected function init():void { ExternalInterfa ...
- Python利用subprocess起进程
from multiprocessing import Process, Pool import time import subprocess def task(msg): print 'hello, ...
- python 获取当前执行的命令 处于什么文件内
https://stackoverflow.com/questions/3718657/how-to-properly-determine-current-script-directory-in-py ...
随机推荐
- jQuery 滑动
jQuery 滑动方法 通过 jQuery,您可以在元素上创建滑动效果. jQuery 拥有以下滑动方法: slideDown() slideUp() slideToggle() jQuery sli ...
- Laravel 的HTTP控制器
简介# 除了在路有文件中以闭包的形式定义所有的请求处理逻辑外,还可以使用控制器类来组织此类行为,控制器能够将相关 的请求处理逻辑组成的一个单独的类,控制器被存放在app/Http/Controller ...
- 2019-2-24-VisualStudio-过滤输出窗口文本
title author date CreateTime categories VisualStudio 过滤输出窗口文本 lindexi 2019-2-24 11:10:7 +0800 2019-0 ...
- 【转载】字符编码笔记:ASCII,Unicode和UTF-8
字符编码笔记:ASCII,Unicode和UTF-8 作者: 阮一峰 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直 ...
- OO第四单元博客作业
OO第四单元博客作业 BUAA_1706_HugeGun 目录 第四单元作业架构设计 四个单元架构设计及OO方法理解 四个单元测试理解与实践演进 课程收获 一点建议 第四单元作业架构设计 ### 第十 ...
- Java 简单校验框架
数据校验框架现状 在我们的方法入口后面,难免会有如下样子的代码: result.setSuccess(false); if (StringUtils.isBlank(bizOrder.getThird ...
- nio FileChannel中文乱码问题
最近用nio读取文件时,英文正常,读取中文时会出现乱码,经查可以用Charset类来解决: 代码如下: package com.example.demo; import java.io.FileNot ...
- supersocket Silverlight 策略服务器
<?xml version="1.0"?> <configuration> <configSections> <section name= ...
- mybatis 基础理解resultType和resultMap
resultType和resultMap: 1.resultType: 一.返回一般数据类型比如要根据 id 属性获得数据库中的某个字段值. mapper (dao)接口: // 根据 id 获得数据 ...
- JS精度问题,解决方案 math.js
JS精度问题 Vue中使用 解决方案 math.js npm install mathjs import { create, all } from 'mathjs' const config = ...