Python实现shell指令执行

1、前言

实现在shell中执行指令,在Python中可以有两种方法实现,一种是通过Python内置的os库,另一种是通过subprocess库。在os库中,有popen()方法可以执行指令,而subprocess中有Popen()方法,两者名称一样,需要注意大小写。下面是具体的使用示例。

2、os.popen方法

2.1、非阻塞命令执行

内置os库的popen方法,非阻塞使用示例如下:

import os
print(os.popen("adb devices"))

正常执行,会返回执行结果的内存值,这里不会展示命令执行的结果:

image-20240116105825860

如果只是想在代码中增加一个命令执行,可以使用这个方法,通过这种方式增加的命令执行为非阻塞的。缺点在于不会打印命令执行的结果。

验证阻塞:

import os
# 此命令会一直执行
print(os.popen('adb shell "ping 127.0.0.1"'))
# 正常打印下面内容
print("阻塞验证")

Tips:在Python中实现多行输入,键入即可换行继续输入。

2.2、阻塞式命令执行

在上述方法中,os.popen()本质上是不阻塞的,那为了实现阻塞功能,可以增加一个read()readlines()方法1。当前命令未执行完毕不会进入下一步的代码执行,除非使用Ctrl+C关闭程序。

import os
print(os.popen("adb devices").read())

image-20240116110623924

执行过程,会读取内存值,并将其返回。这里会返回命令执行的结果,但其会阻塞下一步代码的执行。

验证阻塞:

import os
print(os.popen('adb shell "ping 127.0.0.1"').read())
# 不会打印下面内容
print("阻塞验证")

当我们指令的执行存在前后依赖关系,这时候可使用阻塞式执行方法了。

3、subprocess.Popen方法

3.1、非阻塞命令执行

使用subprocess库中的Popen()方法,同样可以执行shell命令,其本质是新开一个线程,来异步执行命令,使用方法如下:

import subprocess
# print(subprocess.Popen(“xxx”))会打印执行指令内存地址
subprocess.Popen('adb shell "ping 127.0.0.1"')
subprocess.Popen("adb devices")

上述示例,两个指令执行不会受顺序的影响,是非阻塞的关系:

image-20240116115511724

3.2、阻塞命令执行

使用wait()communicate()方法2,使其阻塞下一条指令的执行:

import subprocess
sprocess1 = subprocess.Popen('adb shell "ping 127.0.0.1"')
# sprocess1.communicate()
sprocess1.wait()
subprocess.Popen("adb devices")

两种类型执行结果如下,后面的adb devices指令不会继续执行:

image-20240116121452020

如果想定时阻塞,可以使用Popen.wait(timeout=0)增加timeout超时时间,到达时间后会执行下一步指令。

4、总结

上述的方法,可以方便我们在外部(PC)实现shell指令的一些自动化,其中的一些阻塞关系可以交叉使用,以适配进程之间的同步、异步等关系,无论是阻塞亦或是非阻塞,两者的选用需要根据实际场景中指令见的依赖关系来选择。


  1. https://blog.51cto.com/u_2681882/2317053 ??

  2. https://blog.csdn.net/huakai_sun/article/details/79682172 ??