0%

python-执行外部命令的几种方式

os.system

  • 执行的时候程序会打出cmd在linux上执行的信息
  • 执行命令成功返回为0,否则为1
  • 如果想获取在cmd输出的内容,是没办法获到的
    1
    2
    3
    4
    t2 = os.system("1adb devices")
    t3 = os.system("adb devices")
    print(t2) # 打印为1
    print(t3) # 打印为0

subprocess.call

  • 取代os.system,但是也是无法获取cmd输出的内容
1
2
3
import subprocess
t = subprocess.call('adb devices')
print(t) # 打印为0

os.popen

  • popen返回的是一个file对象,跟open打开文件一样操作了,r是以读的方式打开
1
2
output = os.popen('adb devices')
print(output.read()) # 得到List of devices attached

subprocess.Popen

  • subprocess模块代替os.systemos.popen,能够得到命令输出的值

shell参数

  • linux下,当shell=False(默认)时,Popen使用os.execvp()来执行子程序。args一般要是一个【列表】。如果args是个字符串的
    话,会被当做是可执行文件的路径,这样就不能传入任何参数了。
    1
    2
    3
    subprocess.Popen("cat test.txt", shell=True)
    这是因为它相当于
    subprocess.Popen(["/bin/sh", "-c", "cat test.txt"])

stdin stdout stderr 参数

  • 分别表示程序的标准输入、输出、错误句柄。他们可以是PIPE,文件描述符或文件对象,也可以设置为None表示从父进程继承
  • 执行结果使用管道输出的实例:
1
2
pipe=subprocess.Popen("adb devices",shell=True,stdout=subprocess.PIPE).stdout
print(pipe.read()) # 得到值b'List of devices attached\r\n\r\n'
  • 执行结果保存在文件实例

    1
    2
    3
    4
    cmd = "adb shell ls /sdcard/ | findstr aa.png"  
    fhandle = open(r"e:\aa.txt", "w")
    pipe = subprocess.Popen(cmd, shell=True, stdout=fhandle).stdout
    fhandle.close()
  • 子进程的文本流控制

    1
    2
    3
    4
    5
    6
    7
    8
    #!/usr/bin/env python

    import subprocess

    child1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
    child2 = subprocess.Popen(["wc"], stdin=child1.stdout,stdout=subprocess.PIPE)
    out = child2.communicate()
    print out
  • child1.stdout–>subprocess.PIPE

  • child2.stdin<–subprocess.PIPE

  • child2.stdout–>subprocess.PIPE

  • 相当于将child1.stdout–>child2.stdin->child2.stdout->subprocess.PIPE

  • subprocess.PIPE实际上为文本流提供一个缓存区。child1的stdout将文本输出到缓存区,随后child2的stdin从该PIPE中将文本读取走。child2的输出文本也被存放在PIPE中,直到communicate()方法从PIPE中读取出PIPE中的文本。

  • 要注意的是,communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成。

  • 我们还可以利用communicate()方法来使用PIPE给子进程输入:

    1
    2
    3
    import subprocess
    child = subprocess.Popen(["cat"], stdin=subprocess.PIPE)
    child.communicate("vamei") //()不为空,则写入subprocess.PIPE,为空,则从subprocess.PIPE读取
  • subprocess.PIPE–>child.stdin

  • commiuncate相当于写入subprocess.PIPE,然后child从subprocess.PIPE读取

  • 利用python的subprocess模块执行外部命令, 并捕获stdout, stderr的输出

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    import subprocess


    # print ’popen3:’

    def external_cmd(cmd, msg_in=''):
    try:
    proc = subprocess.Popen(cmd,
    shell=True,
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    )
    stdout_value, stderr_value = proc.communicate(msg_in)
    return stdout_value, stderr_value
    except ValueError as err:
    # log("ValueError: %s" % err)
    return None, None
    except IOError as err:
    # log("IOError: %s" % err)
    return None, None


    if __name__ == '__main__':
    stdout_val, stderr_val = external_cmd('dir')
    print ('Standard Output: %s' % stdout_val)
    print ('Standard Error: %s' % stderr_val)
  • 得到命令的返回值,wait

    1
    2
    p=subprocess.Popen("dir", shell=True)  
    p.wait()
  • 但是Popen函数有一个缺陷,就是它是一个阻塞的方法。如果运行cmd时产生的内容非常多,函数非常容易阻塞住。解决办法是不使用wait()方法,但是也不能获得执行的返回值了。

commands.getstatusoutput

  • 不推荐使用,因为在python3中被废弃