外部程序,测试人员最长使用adb程序,在Python程序中调用adb程序,称为调用外部程序,你可能用过os.system()、os.popen()等等方式,官方推荐的是subprocess模块中的run()函数,今天就把python中所有可用于调用外部程序的方式都写他它一遍,各位方便用哪个都可以!
os模块下的system函数,可用于执行外部程序,传入参数为具体的命令,比如
import os
os.system("adb devices")
print("haha,我会等上面的程序执行完毕")
输出
List of devices attached
haha,我会等上面的程序执行完毕
特点1:List of devices attached 是 adb devices的标准输出,也就是说外部程序在子进程中的标准输出,也会和python当前主进程的标准输出中一起输出,从进程角度看,子进程使用父进程的标准输出,太正常不过了!
特点2:子进程中执行外部命令时,会阻塞当前python脚本进程的进度,所以你看到了:haha,我会等上面的程序执行完毕的输出
特点3:os.system()根据平台的不同(类Linux或者Windows),返回值表示退出状态码
特点4:无法在程序中获取到外部程序的标准输出,不方便我们在程序处理
特点5:完全绕开了bash,与bash无关,这里是直接执行了程序adb
特点6:标准错误也会和父进程中的输出在一起
os模块下的popen函数,3个参数,第一个参数表示命令、第二个参数表示模式(r表示读管道、w表示写管道),第三个参数表示管道缓冲区大小,返回是个类似file的对象,具体是os模块下的_wrap_close类的对象,返回值是代表连接到管道的文件对象
import os
file_like = os.popen("adb devices")
print(file_like.read())
print("haha,我会等上面的程序执行完毕")
特点1:内部使用subprocess.Popen 实现
特点2:由于返回的是一个代表管道的文件对象,read()方法可以获取外部程序的所有标准输出,返回的是一个字符串
特点3:常用的readlines(),以换行符作为分隔,返回一个包含所有标准输出的list,每行一个元素
特点4:waitstatus_to_exitcode() 可以将 close()
方法的返回值转为退出状态码
特点5:同样会阻塞当前主进程的执行流,直到子进程中程序执行完毕
import subprocess
output = subprocess.getoutput("adb devices")
print(output)
print("等待外部程序执行结束")
特点1:内部使用subprocess.getstatusoutput()实现
特点2:可以方便的获取标准输出
特点3:同样会阻塞python主进程的执行,直到拿到外部程序的标准输出
import subprocess
output = subprocess.getstatusoutput("adb devices")
print(output)
print("等待外部程序执行结束")
特点1:内部使用subprocess.check_output()
特点2:返回值是个元组,类似这样。(0, 'List of devices attached\n'),第一个元素代表退出状态码、第二个元素代表标准输出
import subprocess
output = subprocess.check_output("adb devices")
print(output)
print("等待外部程序执行结束")
特点1:内部使用subprocess.run()
特点2:返回的是字节串对象,而不是字符串对象,需要自行转换
特点3:可以控制标准错误、外部程序执行时间、录入标准输入、是否使用bash等等选项(注意:默认情况下并没有经过bash解释器)
特点4:退出状态码非0,抛出的异常是CalledProcessError
特点5:待续
import subprocess
output = subprocess.run("adb devices")
print(output)
print("等待外部程序执行结束")
输出
List of devices attached
CompletedProcess(args='adb devices', returncode=0)
等待外部程序执行结束
特点1:内部使用subprocess.Popen类,每个Popen对象代表子进程
特点2:默认外部程序的标准输出,使用python进程器主进程的标准输出
特点3:默认返回为CompletedProcess对象
特点4:这个可以更灵活的控制子进程中执行的程序,标准输入、标准输出、标准错误、退出状态码等等随便拿着用
import subprocess
output = subprocess.Popen("adb devices")
print(output)
print("等待外部程序执行结束")
特点1:可以最大程序的控制子进程中执行程序
特点2:替代os模块在子进程中执行程序
特点3:返回的是Popen对象
import subprocess
output = subprocess.call("adb devices")
print(output)
print("等待外部程序执行结束")
特点1:返回值为退出状态码
特点2:同样会等待子进程执行程序结束
import subprocess
output = subprocess.check_call("adb devices")
print(output)
print("等待外部程序执行结束")
特点1:依赖subprocess.call()
特点2:返回值退出状态码,非0时返回CalledProcessError对象
1、官方提供这么多种执行外部程序的方式,我相信与标准的制定有关,每个方式都不完美,但总有适合你的
2、它们都会阻塞当前进程
3、官方建议使用subprocess下的方式,而不建议使用os下的方式
4、subprocess模块的源码非常值得一读
5、肯定还有其他调用外部程序的方式,不过这些真的够用了