【命令】Python中的执行命令【原创】

 

参考

官方手册

python中os.system、os.popen、subprocess.popen的区别

Python执行系统命令的方法 os.system(),os.popen(),commands

Python subprocess模块功能与常见用法实例详解

一、概要

由于之前接触了一个项目,做发布系统,其中需要去git拉代码并且checkout到对应的Tag或者是分支,这就要求需要使用Python来执行系统命令,于是开始接触到了Python中的执行命令

如果想要在Python中调用cmd指令,有四种方法:

  • os.system
  • os.popen
  • commands(Python3已废除)
  • subprocess模块

二、os.system

用来执行cmd指令,在cmd输出的内容会直接在控制台输出,返回结果为0表示执行成功

system()函数在执行过程中进行了以下三步操作:

  • fork一个子进程
  • 在子进程中调用exec函数去执行命令
  • 在父进程调用wait(阻塞)去等待子进程结束

对于fork失败,system函数会返回-1

注意: 由于使用该函数经常会莫名其妙地出现错误,但是直接执行命令并没有问题,所以一般建议不要使用。

注意:os.system是简单粗暴的执行cmd指令,如果想获取在cmd输出的内容,是没办法获到的

注意:在Unix,Windows都有效

三、os.popen

同样是用来执行cmd指令,如果想获取控制台输出的内容,那就用os.popen的方法了,popen返回的是一个file对象,跟open打开文件一样操作了,r是以读的方式打开

popen() 创建一个管道,通过fork一个子进程,然后该子进程执行命令。返回值在标准IO流中,该管道用于父子进程间通信。父进程要么从管道读信息,要么向管道写信息,至于是读还是写取决于父进程调用popen时传递的参数(w或r)

比如:

#!/usr/bin/python
import os

p=os.popen('ssh 10.3.16.121 ls')
x=p.read()
print x
p.close()

注意:能获取到命令的执行内容,可以打印出来,但是获取不到命令是否执行成功,只是单纯输出了命令的执行结果而已

注意:os.popen() 方法用于从一个命令打开一个管道。在Unix,Windows中有效

四、subprocess模块

subprocess模块是在2.4版本中新增的,官方文档中描述为可以用来替换以下函数:os.system、os.spawn、os.popen、popen2

参数既可以是string字符串,也可以是list列表

比如:

subprocess.Popen([“cat”,”test.txt”])
subprocess.Popen(“cat test.txt”, shell=True) 

对于参数是字符串,需要指定shell=True,官方建议使用list列表

参数有:

比如:subprocess.call代替os.system

执行命令,返回命令的结果和执行状态,0或者非0

import subprocess

retcode = subprocess.call('ls -l', shell=True)
print(retcode)

比如:subprocess.getstatusoutput()

接受字符串形式的命令,返回 一个元组形式的结果,第一个元素是命令执行状态,第二个为执行结果

比如:

#执行正确
>>> subprocess.getstatusoutput('pwd')
(0, '/root')
#执行错误
>>> subprocess.getstatusoutput('pd')
(127, '/bin/sh: pd: command not found')

比如:subprocess.getoutput()

接受字符串形式的命令,返回执行结果

#执行正确
>>> res = subprocess.getoutput('pwd')
>>> res
'/d/software/laragon/www/test/AutoRelease'
#执行错误
>>> res = subprocess.getoutput('ip addr')
>>> res
"'ip' 不是内部或外部命令,也不是可运行的程序\n或批处理文件。"

以及还有check_output()、check_call()、run()等

注意:官方建议使用run函数,run函数是在Python 3.5增加的(https://docs.python.org/zh-cn/3.7/library/subprocess.html#module-subprocess)

>>> import subprocess
# python 解析则传入命令的每个参数的列表
>>> subprocess.run(["df","-h"])
Filesystem      Size Used Avail Use% Mounted on
/dev/mapper/VolGroup-LogVol00
           289G  70G 204G 26% /
tmpfs         64G   0  64G  0% /dev/shm
/dev/sda1       283M  27M 241M 11% /boot
CompletedProcess(args=['df', '-h'], returncode=0)
# 需要交给Linux shell自己解析,则:传入命令字符串,shell=True
>>> subprocess.run("df -h|grep /dev/sda1",shell=True)
/dev/sda1       283M  27M 241M 11% /boot
CompletedProcess(args='df -h|grep /dev/sda1', returncode=0)

以上subprocess使用的方法,都是对subprocess.Popen的封装

五、代码

注意:以下代码在Windows执行,会有一些问题,最好是在Linux下运行

os.system

# -*- coding:utf-8 -*-
import os


def run_cmd(string):
    print("命令为:" + cmd)
    return os.system(string)


path = 'D:/software/laragon/test/'
cmd = "cd %s && rm -rf ./*" % path
res1 = run_cmd(cmd)

if res1 != 0:
    print("命令出错了")
else:
    print("命令成功了")

git_url = 'http://xxx/AutoRelease.git'
cmd = "cd %s && git clone %s" % (path, git_url)
res2 = run_cmd(cmd)
if res2 != 0:
    print("命令出错了")
else:
    print("命令成功了")

tag = 'v20190824'
cmd = "cd %s/AutoRelease && git checkout %s" % (path, tag)
res3 = run_cmd(cmd)
if res3 != 0:
    print("命令出错了")
else:
    print("命令成功了")

cmd = "ls -al"
res4 = run_cmd(cmd)
if res4 != 0:
    print("命令出错了")
else:
    print("命令成功了")

# Windows下报错,Linux下不报错
cmd = "ip addr"
res5 = run_cmd(cmd)
if res5 != 0:
    print("命令出错了")
else:
    print("命令成功了")

# Windows不报错,Linux下报错
cmd = "ipconfig"
res6 = run_cmd(cmd)
if res6 != 0:
    print("命令出错了")
else:
    print("命令成功了")

os.popen

同样是实现上面的内容,但是结果却不同:

# -*- coding:utf-8 -*-
import os


def run_cmd(string):
    print("命令为:" + cmd)
    output = os.popen(string)
    ret = output.read()
    output.close()
    return ret


path = 'D:/software/laragon/test/'
cmd = "cd %s && rm -rf ./*" % path
res1 = run_cmd(cmd)
print('命令的结果为:' + res1 + "\r\n")

git_url = 'http://xxx/AutoRelease.git'
cmd = "cd %s && git clone %s" % (path, git_url)
res2 = run_cmd(cmd)
print('命令的结果为:' + res2 + "\r\n")

tag = 'v20190824'
cmd = "cd %s/AutoRelease && git checkout %s" % (path, tag)
res3 = run_cmd(cmd)
print('命令的结果为:' + res3 + "\r\n")

cmd = "ls -al"
res4 = run_cmd(cmd)
print('命令的结果为:' + res4 + "\r\n")

cmd = "ip addr"
res5 = run_cmd(cmd)
print('命令的结果为:' + res5 + "\r\n")

# Windows不报错,Linux下报错
cmd = "ipconfig"
res6 = run_cmd(cmd)
print('命令的结果为:' + res6 + "\r\n")

这个Python运行后,只有第四条和第六条命令能打印出来结果,也就是ls -al和ipconfig能打印出来,其他的命令只能在控制台看到输出结果,却打印不出来,并且也不知道执行的状态是否成功

suprocess

# -*- coding:utf-8 -*-
import subprocess


def run_cmd(string):
    print("命令为:" + cmd)
    (code, res) = subprocess.getstatusoutput(string)
    return code, res


path = 'D:/software/laragon/test/'
cmd = "cd %s && rm -rf ./*" % path
(code, res) = run_cmd(cmd)
if code != 0:
    print("命令出错了")
else:
    print("命令成功了")
print('命令的结果为:' + res + "\r\n")

git_url = 'http://xxx/AutoRelease.git'
cmd = "cd %s && git clone %s" % (path, git_url)
(code, res) = run_cmd(cmd)
if code != 0:
    print("命令出错了")
else:
    print("命令成功了")
print('命令的结果为:' + res + "\r\n")

tag = 'v20190824'
cmd = "cd %s/AutoRelease && git checkout %s" % (path, tag)
(code, res) = run_cmd(cmd)
if code != 0:
    print("命令出错了")
else:
    print("命令成功了")
print('命令的结果为:' + res + "\r\n")

cmd = "ls -al"
(code, res) = run_cmd(cmd)
if code != 0:
    print("命令出错了")
else:
    print("命令成功了")
print('命令的结果为:' + res + "\r\n")

cmd = "ip addr"
(code, res) = run_cmd(cmd)
if code != 0:
    print("命令出错了")
else:
    print("命令成功了")
print('命令的结果为:' + res + "\r\n")

# Windows不报错,Linux下报错
cmd = "ipconfig"
(code, res) = run_cmd(cmd)
if code != 0:
    print("命令出错了")
else:
    print("命令成功了")
print('命令的结果为:' + res + "\r\n")
发布了64 篇原创文章 · 获赞 47 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/jiandanokok/article/details/100056743