轻松使用python调用系统shell执行命令行命令的几种方式!

在这里插入图片描述

在使用python时总免不了会使用到命令行来帮我们执行命令,尤其是在linux系统中就更为常见了,若是熟悉shell编程的当然可以直接使用shell写个脚本,但奈何我不熟呀。因此我还是乖乖的在python中调用一下命令行来执行命令吧。

本文将介绍几个常见的用于调用命令行执行命令的方式。


os模块

首先,最常用也最方便的就是os模块了,os模块能执行的命令很多,这里只介绍调用命令行的方式,os模块调用命令行的方式有os.system和os.popen两种。

os.system

使用os.system方法能轻而易举的执行命令行命令,使用方式为:

import os
command ='start cmd'     # 开启cmd,这里只能在window中使用,是开启cmd命令行的命令
# 要传给os.system()函数的参数为字符串形式,这些字符串最终被系统的命令行当作命令
# 直接运行,因此传入的字符串需要严格按照命令行命令书写的语法来编辑,当然也可以
# 传入变量,这些变量会在python中被解析,最终传递给命令行的命令是被解析完全的字符串。
os.system(command)

需要注意的是,os.system的原理为开启子进程,子进程结果无法影响其它子进程,因此若多个命令需要同时运行(如有先后顺序的命令),可以直接在os.system中写入两个命令即可,如:

import os
dir_name = 'new_dir'   # 这里添加一个变量
command = f'cd~ && mkdir {dir_name}'   
# 使用&&符号表示前面命令执行后才执行后面的命令
# 这里的意思是到主目录下创建一个文件夹,文件夹名是传入的变量
os.system(command)

os.popen

使用os.popen方法也能执行命令行命令,但os.popen与os.system的返回值不同,os.system的返回值为退出状态码(即是否正常退出),而os.popen的返回值为命令执行在命令行上得到的输出结果,这些输出结果被以文件对象的形式返回,如以下的例子中的f可以像文件对象一样被操作,如f.read()、f.readlines()、f.readline()等等。同时popen的语法支持’r’、'w’两种模式,和文件对象一样,若使用’w’模式,那么便不能被读取到,默认使用的’r’模式可以被读取。使用方式为:

import os
f = os.popen('ls')
print(f.readlines())
# 这里得到的结果为当前目录下的所有文件,并被列为一个列表了。
# 如在python文件夹中运行这个命令的结果:
# ['bin\n', 'etc\n', 'ete3\n', 'include\n', 'lib\n', 'share\n']

subprocess模块

在subprocess的官方模块介绍中,明确提出了这个模块就是为替代一些旧的调用命令行的方法而来的。官方介绍为:subprocess 模块允许你生成新的进程,连接它们的输入、输出、错误管道,并且获取它们的返回码。此模块打算代替一些老旧的模块与功能。总结一下其比之前的方法多出的优点为:能连接进程的输入、输出、错误管道、获取其返回码。所以上面提到的os.popen方法和os.system模块的功能都能被subprocess完成之外,同时subprocess完成的功能还更多。但是我们还是可以根据工作需要选择的,毕竟os.popen和os.system用起来确实简单。

在subprocess模块中,有很多的方法如call、Popen、run等,但是推荐使用的就是run方法了,其能完成大部分的工作。实际上这些方法在底层是调用Popen方法,但有时候还是会用到Popen方法,这就如正则表达式中都是调用re.compile模块,但有时候还是会直接使用re.compile。

subprocess.run

subprocess.run的使用方式:

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None, **other_popen_kwargs)

这里简要介绍一下上面的几个参数,

  • args就是要执行的命令(字符串形式),*号后就是命名关键字参数了(之前有介绍过)
  • stdout, stderr,input: 这些参数是管道相关命令,用于进程与其它文件或者进程之间的沟通,关于管道的部分就不多讲了
  • shell,表示是否使用shell程序如sh,若为True则表示使用shell这样的壳来执行,也就是执行的时候会有/bin/sh这样的前缀,而若为False表示要执行的命令是可执行文件,执行所依赖的并不是shell这个壳(有博主介绍说是依赖os.execvp()这个命令),因此其不能使用到如管道符|;&这些符号。shell=False时其接受数组变量(如列表)作为命令,但是只识别第一个元素为命令,其余都被识别为参数。使用shell=True的话与shell命令使用方式相同,传入的命令必须为字符串形式,这样也会增加出现错误的可能性,这里读者可以自行尝试一下两者的不同。
  • cwd可以调整命令执行的目录

subprocess.run的返回值为一个CompletedProcess类的类实例,它包含了命令的参数,返回状态等信息,因此可以在类实例中获取某些信息。这里简单展示一下subprocess.run的基础使用方式:

>>> import subprocess
>>> a = subprocess.run('ls -h -a', shell = True)
.  ..  bin  etc  ete3  include	lib  share
# ls -h -a查看当前目录下的所有文件及文件夹
# 这里如果shell为False会报错
>>> print(a)
CompletedProcess(args='ls -h -a', returncode=0)
# 运行结果a为类实例,可以看到返回状态和参数

使用shell=False的方法:

>>> import subprocess
>>> a = subprocess.run(['ls', '-h', '-a'], shell = False)
.  ..  bin  etc  ete3  include	lib  share
# 使用时将命令和参数都放到列表数组中,第一个元素为命令,后面的都为参数
>>> print(a)
CompletedProcess(args=['ls', '-h', '-a'], returncode=0)
# 同上

subprocess.call、subprocess.Popen等

正如subprocess.run一节提到了,使用subprocess.call(返回值为进程退出码)subprocess.Popen(底层调用的基础,使用灵活性更强)或其它的一些如subprocess.check_output(附带参数运行命令并返回其输出)subprocess.getoutput(返回在 shell 中执行 cmd 产生的输出(stdout 和 stderr)等都可以执行命令行命令,但是执行它们得到的返回值不一样,这也正是为什么会有这些不同的方法的原因,此外可能还会有一定的其它不同,但是使用它们的方式是类似的,若是需要使用时可以再去查查。

除了上面的两大模块外,之前还有一个commands模块也用于执行命令行命令,其可以获取在命令行执行命令所输出的结果,但是现在已经不推荐用了,此处也不再介绍了。毕竟已经有更适合做这些的方法了。

本文主要参考网上内容,若是有错还望海涵并指出,我将尽快改正。

参考:https://www.yht7.com/news/141304
参考:
https://docs.python.org/zh-cn/3/library/subprocess.html#subprocess.run

参考:https://www.cnblogs.com/zhou2019/p/10582716.html

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值