- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Python实现subprocess执行外部命令由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
subprocess 模块允许我们启动一个新进程,并连接到它们的输入/输出/错误管道,从而获取返回值.
这个模块用来创建和管理子进程。它提供了高层次的接口,用来替换os.system*()、 os.spawn*()、 os.popen*()、os,popen2.*()和commands.*等模块和函数.
subprocess提供了一个名为Popen的类启动和设置子进程的参数,由于这个类比较复杂, subprocess还提供了若干便利的函数,这些函数都是对Popen类的封装.
linux安装ipython 。
pip3 install ipython
(1)call函数 。
call函数的定义如下
subprocess.ca11(args, *, stdin=None, stdout=None, stderr=None, she11=False)#运行由args参数提供的命令,等待命令执行结束并返回返回码。args参数由字符串形式提供且有多个命令参数时,需要提供shell=True参数
示例代码
[root@python ~]# ipython #启动ipythonPython 3.8.1 (default, Mar 9 2020, 12:35:12) Type "copyright", "credits" or "license" for more informationIPython 7.13.0 -- An enhanced Interactive Python. Type "?" for help.In [1]: import subprocess #调用函数 In [2]: subprocess.call(["ls","-l"]) drwxr-xr-x. 2 root root 6 10月 31 23:04 公共drwxr-xr-x. 2 root root 6 10月 31 23:04 模板drwxr-xr-x. 2 root root 6 10月 31 23:04 视频drwxr-xr-x. 2 root root 4096 10月 31 22:40 图片drwxr-xr-x. 2 root root 6 10月 31 23:04 文档drwxr-xr-x. 2 root root 6 10月 31 23:04 下载drwxr-xr-x. 2 root root 6 10月 31 23:04 音乐drwxr-xr-x. 2 root root 6 10月 31 15:27 桌面Out[2]: 0In [3]: subprocess.call("exit 1",shell=True) Out[3]: 1
(2)check_call函数 。
check_call函数的作用与call函数类似,区别在于异常情况下返回的形式不同.
对于call函数,工程师通过捕获call命令的返回值判断命令是否执行成功,如果成功则返回0,否则的话返回非0,对于check_call函数,如果执行成功,返回0,如果执行失败,抛出subrocess.CalledProcessError异常。如下所示:
In [5]: subprocess.check_call(["ls","-l"])drwxr-xr-x. 2 root root 6 10月 31 23:04 公共drwxr-xr-x. 2 root root 6 10月 31 23:04 模板drwxr-xr-x. 2 root root 6 10月 31 23:04 视频drwxr-xr-x. 2 root root 4096 10月 31 22:40 图片drwxr-xr-x. 2 root root 6 10月 31 23:04 文档drwxr-xr-x. 2 root root 6 10月 31 23:04 下载drwxr-xr-x. 2 root root 6 10月 31 23:04 音乐drwxr-xr-x. 2 root root 6 10月 31 15:27 桌面Out[5]: 0In [6]: subprocess.check_call("exit 1",shell=True) -------------------------------------------------------------CalledProcessError Traceback (most recent call last)<ipython-input-6-5e148d3ce640> in <module>----> 1 subprocess.check_call("exit 1",shell=True)/usr/local/python381/lib/python3.8/subprocess.py in check_call(*popenargs, **kwargs) 362 if cmd is None: 363 cmd = popenargs[0]--> 364 raise CalledProcessError(retcode, cmd) 365 return 0 366CalledProcessError: Command "exit 1" returned non-zero exit status 1.
(3)check_output 。
Python3中的subprocess.check_output函数可以执行一条sh命令,并返回命令的输出内容,用法如下:
In [10]: output = subprocess.check_output(["df","-h"]) In [11]: print(output.decode()) 文件系统 容量 已用 可用 已用% 挂载点/dev/mapper/cl-root 17G 5.2G 12G 31% /devtmpfs 473M 0 473M 0% /devtmpfs 489M 92K 489M 1% /dev/shmtmpfs 489M 7.1M 482M 2% /runtmpfs 489M 0 489M 0% /sys/fs/cgroup/dev/sda1 1014M 173M 842M 18% /boottmpfs 98M 16K 98M 1% /run/user/42tmpfs 98M 0 98M 0% /run/user/0In [12]: lines = output.decode().split("")In [13]: lines Out[13]: ["文件系统 容量 已用 可用 已用% 挂载点", "/dev/mapper/cl-root 17G 5.2G 12G 31% /", "devtmpfs 473M 0 473M 0% /dev", "tmpfs 489M 92K 489M 1% /dev/shm", "tmpfs 489M 7.1M 482M 2% /run", "tmpfs 489M 0 489M 0% /sys/fs/cgroup", "/dev/sda1 1014M 173M 842M 18% /boot", "tmpfs 98M 16K 98M 1% /run/user/42", "tmpfs 98M 0 98M 0% /run/user/0", ""]In [14]: for line in lines[1:-1]: ...: if line: ...: print(line.split()[-2]) ...: #截取挂载点数据 31%0%1%2%0%18%1%0%
在子进程执行命令,以字符串形式返回执行结果的输出。如果子进程退出码不是0,抛出subprocess.CalledProcessError异常,异常的output字段包含错误输出:
In [19]: try: ...: output = subprocess.check_output(["df","-h"]).decode() #正确的 ...: except subprocess.CalledProcessError as e: ...: output = e.output ...: code = e.returncode //正确的没有任何输出 。
In [23]: try: ...: output = subprocess.check_output(["wsd","-h"], stderr=subprocess.STDOUT) ...: .decode() #错误的 ...: except subprocess.CalledProcessError as e: ...: output = e.output ...: code = e.returncode ...: 。
//前面的错误代码省略 FileNotFoundError: [Errno 2] No such file or directory: "wsd" 。
实际上,我们上面的三个函数都是基于Popen()的封装(wrapper)。这些封装的目的在于让我们容易使用子进程。当我们想要更个性化我们的需求的时候,就要转向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=False, startupinfo=None, creationflags=0,restore_signals=True, start_new_session=False, pass_fds=(),*, encoding=None, errors=None)
(1)常用参数: args:shell命令,可以是字符串或者序列类型(如:list,元组) bufsize:缓冲区大小。当创建标准流的管道对象时使用,默认-1.
stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄 preexec_fn:只在 Unix 平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用 shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令。 cwd:用于设置子进程的当前目录。 env:用于指定子进程的环境变量。如果 env = None,子进程的环境变量将从父进程中继承.
创建一个子进程,然后执行一个简单的命令:
>>> import subprocess>>> p = subprocess.Popen("ls -l", shell=True)>>> total 164-rw-r--r-- 1 root root 133 Jul 4 16:25 admin-openrc.sh-rw-r--r-- 1 root root 268 Jul 10 15:55 admin-openrc-v3.sh...>>> p.returncode>>> p.wait()0>>> p.returncode0
这里也可以使用 p = subprocess.Popen(["ls", "-cl"]) 来创建子进程.
(2)Popen 对象的属性 。
<1> p.pid: 子进程的PID.
<2> p.returncode: 该属性表示子进程的返回状态,returncode可能有多重情况:
<3> p.stdin, p.stdout, p.stderr: 子进程对应的一些初始文件,如果调用Popen()的时候对应的参数是subprocess.PIPE,则这里对应的属性是一个包裹了这个管道的 file 对象.
(3)Popen 对象方法 。
子进程的PID存储在child.pid 。
import timeimport subprocessdef cmd(command): subp = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding="utf-8") subp.wait(2) if subp.poll() == 0: print(subp.communicate()[1]) else: print("失败")cmd("java -version")cmd("exit 1")
输出结果如下:
java version "1.8.0_31" Java(TM) SE Runtime Environment (build 1.8.0_31-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode) 。
失败
(4)子进程的文本流控制 (沿用child子进程) 子进程的标准输入,标准输出和标准错误也可以通过如下属性表示
我们可以在Popen()建立子进程的时候改变标准输入、标准输出和标准错误,并可以利用subprocess.PIPE将多个子进程的输入和输出连接在一起,构成管道(pipe)
import subprocesschild1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)child2 = subprocess.Popen(["wc"], stdin=child1.stdout,stdout=subprocess.PIPE)out = child2.communicate()print(out)
执行结果如下:
(b" 2 11 60 ", None) 。
subprocess.PIPE实际上为文本流提供一个缓存区。child1的stdout将文本输出到缓存区,随后child2的stdin从该PIPE中将文本读取走。child2的输出文本也被存放在PIPE中,直到communicate()方法从PIPE中读取出PIPE中的文本.
要注意的是,communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成.
我们还可以利用communicate()方法来使用PIPE给子进程输入
import subprocesschild = subprocess.Popen(["cat"], stdin=subprocess.PIPE)child.communicate("vamei".encode())
我们启动子进程之后,cat会等待输入,直到我们用communicate()输入"vamei".
通过使用subprocess包,我们可以运行外部程序。这极大的拓展了Python的功能。如果你已经了解了操作系统的某些应用,你可以从Python中直接调用该应用(而不是完全依赖Python),并将应用的结果输出给Python,并让Python继续处理。shell的功能(比如利用文本流连接各个应用),就可以在Python中实现.
PyCharm记得连接linux 。
简易流程 。
subprocess.call(["ls","-l"])subprocess.call("ll" , shell=True)
运行成功: 返回0 运行失败: 返回非0 。
subprocess. check_call (["ls", "-l"])subprocess. check_call ("ll", shell=True)
运行成功: 返回0 运行失败: 返回CalledProcessError 。
subprocess. check_ output(["cat", "apache.log"], stderr= subprocess.STDOUT)
运行成功:返回命令的输出结果 运行失败:自定义错误输出stderr 。
subprocess模块的Popen类 。
(1)PyCharm创建文件 。
# coding=utf-8import subprocessimport osimport shutilimport tarfile# 执行外部命令的函数def execute_cmd(cmd): """执行shell命令""" p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: return p.returncode, stderr return p.returncode, stdout# 解压def unpackage_mongo(package, package_dir): # 获取MongoDB压缩包的主文件名,也就是解压后的目录名称 # mongodb-linux-x86_64-rhe170-4.2.3 unpackage_dir = os.path.splitext(package)[0] if os.path.exists(unpackage_dir): shutil.rmtree(unpackage_dir) if os.path.exists(package_dir): shutil.rmtree(package_dir) # 解压 try: t = tarfile.open(package, "r:gz") t.extractall(".") print("tar is ok.") except Exception as e: print(e) # 重命名 shutil.move(unpackage_dir, "mongo")# 创建mongodatadef create_datadir(data_dir): if os.path.exists(data_dir): shutil.rmtree(data_dir) os.mkdir(data_dir)# 拼接启动MongoDBdef format_mongod_commamd(package_dir, data_dir, logfile): # mongo/bin/mongod mongod = os.path.join(package_dir, "bin", "mongod") # mongo/bin/mongod --fork --logpath mongodata/mongod.log --dbpath mongodata mongod_format = """{0} --fork --dbpath {1} --logpath {2}""" return mongod_format.format(mongod, data_dir, logfile)# 启动MongoDBdef start_mongod(cmd): returncode, out = execute_cmd(cmd) if returncode != 0: raise SystemExit("execute {0} error:{1}".format(cmd, out)) else: print("execute {0} successfuly.".format(cmd))#入口函数def main(): package = "mongodb-linux-x86_64-rhel70-4.2.3.tgz" cur_dir = os.path.abspath(".") package_dir = os.path.join(cur_dir, "mongo") data_dir = os.path.join(cur_dir, "mongodata") logfile = os.path.join(data_dir, "mongod.log") # 判断MongoDB压缩包是否存在 if not os.path.exists(package): raise SystemExit("{0} not found.".format(package)) # 解压 unpackage_mongo(package, package_dir) create_datadir(data_dir) # 启动mongodb start_mongod(format_mongod_commamd(package_dir, data_dir, logfile)) # 配置环境变量 os.system("echo "export PATH=./mongo/bin:$PATH" > ~/.bash_profile") os.system("source ~/.bash_profile") os.system("./mongo/bin/mongo")main()
(2)将PyCharm中的文件上传到Linux 。
如果,是直接调用Linux中文件可用:
如果是本地创建:
(3)Linux执行脚本,并测试 记得进入PyCharm与linux连接的目录(目前是/opt) 。
[root@python opt]# python auto_install_mongodb.py #执行提前编写好的脚本tar is ok.execute /opt/mongo/bin/mongod --fork --dbpath /opt/mongodata --logpath /opt/mongodata/mongod.log successfuly.[root@python opt]# netstat -anpt | grep mongo #查看mongo是否启动tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 4616mongod [root@python opt]# ls #查看是否生成mongo目录01find_cmd.py bb.bmp mongodb-linux-x86_64-rhel70-4.2.3.tgzaaa.jpg cc.png rhadc.txt mongo subprocess_demoauto_install_mongodb.py mongodata[root@python opt]# cd mongo[root@python mongo]# cd bin/[root@python bin]# ./mongo #进入mongoMongoDB shell version v4.2.3connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodbImplicit session: session { "id" : UUID("c302ff50-7e27-40b7-8046-8441af8cb965") }MongoDB server version: 4.2.3> show databases; #查看数据库admin 0.000GBconfig 0.000GBlocal 0.000GB
到此这篇关于Python实现subprocess执行外部命令的文章就介绍到这了,更多相关Python 执行外部命令内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.51cto.com/u_14320361/2491366 。
最后此篇关于Python实现subprocess执行外部命令的文章就讲到这里了,如果你想了解更多关于Python实现subprocess执行外部命令的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
背景: 我最近一直在使用 JPA,我为相当大的关系数据库项目生成持久层的轻松程度给我留下了深刻的印象。 我们公司使用大量非 SQL 数据库,特别是面向列的数据库。我对可能对这些数据库使用 JPA 有一
我已经在我的 maven pom 中添加了这些构建配置,因为我希望将 Apache Solr 依赖项与 Jar 捆绑在一起。否则我得到了 SolarServerException: ClassNotF
interface ITurtle { void Fight(); void EatPizza(); } interface ILeonardo : ITurtle {
我希望可用于 Java 的对象/关系映射 (ORM) 工具之一能够满足这些要求: 使用 JPA 或 native SQL 查询获取大量行并将其作为实体对象返回。 允许在行(实体)中进行迭代,并在对当前
好像没有,因为我有实现From for 的代码, 我可以转换 A到 B与 .into() , 但同样的事情不适用于 Vec .into()一个Vec . 要么我搞砸了阻止实现派生的事情,要么这不应该发
在 C# 中,如果 A 实现 IX 并且 B 继承自 A ,是否必然遵循 B 实现 IX?如果是,是因为 LSP 吗?之间有什么区别吗: 1. Interface IX; Class A : IX;
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在阅读标准haskell库的(^)的实现代码: (^) :: (Num a, Integral b) => a -> b -> a x0 ^ y0 | y0 a -> b ->a expo x0
我将把国际象棋游戏表示为 C++ 结构。我认为,最好的选择是树结构(因为在每个深度我们都有几个可能的移动)。 这是一个好的方法吗? struct TreeElement{ SomeMoveType
我正在为用户名数据库实现字符串匹配算法。我的方法采用现有的用户名数据库和用户想要的新用户名,然后检查用户名是否已被占用。如果采用该方法,则该方法应该返回带有数据库中未采用的数字的用户名。 例子: “贾
我正在尝试实现 Breadth-first search algorithm , 为了找到两个顶点之间的最短距离。我开发了一个 Queue 对象来保存和检索对象,并且我有一个二维数组来保存两个给定顶点
我目前正在 ika 中开发我的 Python 游戏,它使用 python 2.5 我决定为 AI 使用 A* 寻路。然而,我发现它对我的需要来说太慢了(3-4 个敌人可能会落后于游戏,但我想供应 4-
我正在寻找 Kademlia 的开源实现C/C++ 中的分布式哈希表。它必须是轻量级和跨平台的(win/linux/mac)。 它必须能够将信息发布到 DHT 并检索它。 最佳答案 OpenDHT是
我在一本书中读到这一行:-“当我们要求 C++ 实现运行程序时,它会通过调用此函数来实现。” 而且我想知道“C++ 实现”是什么意思或具体是什么。帮忙!? 最佳答案 “C++ 实现”是指编译器加上链接
我正在尝试使用分支定界的 C++ 实现这个背包问题。此网站上有一个 Java 版本:Implementing branch and bound for knapsack 我试图让我的 C++ 版本打印
在很多情况下,我需要在 C# 中访问合适的哈希算法,从重写 GetHashCode 到对数据执行快速比较/查找。 我发现 FNV 哈希是一种非常简单/好/快速的哈希算法。但是,我从未见过 C# 实现的
目录 LRU缓存替换策略 核心思想 不适用场景 算法基本实现 算法优化
1. 绪论 在前面文章中提到 空间直角坐标系相互转换 ,测绘坐标转换时,一般涉及到的情况是:两个直角坐标系的小角度转换。这个就是我们经常在测绘数据处理中,WGS-84坐标系、54北京坐标系
在软件开发过程中,有时候我们需要定时地检查数据库中的数据,并在发现新增数据时触发一个动作。为了实现这个需求,我们在 .Net 7 下进行一次简单的演示. PeriodicTimer .
二分查找 二分查找算法,说白了就是在有序的数组里面给予一个存在数组里面的值key,然后将其先和数组中间的比较,如果key大于中间值,进行下一次mid后面的比较,直到找到相等的,就可以得到它的位置。
我是一名优秀的程序员,十分优秀!