os.system(cmd)的返回值是脚本的退出状态码,只会有0(成功),1,2,返回一个信号代码
os.popen(cmd)返回脚本执行的输出内容作为返回值
os.system方法是os模块最基础的方法,其它的方法一般在该方法基础上封装完成。
详解
os.system()的返回值是脚本的退出状态码,0表示成功,其他均为失败:
import os
a = os.system('adb shell ls -lh /sdcard/tmp/screenshot/')
print(a)
=============================
成功:
-rw-rw---- 1 root sdcard_rw 14 2021-12-20 23:23 1.txt
0
=============================
失败:
error: device not found
-1
system函数可以将字符串转化成命令在服务器上运行;其原理是每一条system函数执行时,其会创建一个子进程在系统上执行命令行,
为了使操作的连续性可以用以下(; )连接命令
例如:
import os
a = os.system('adb shell cd /sdcard/tmp/screenshot/;cat 1.txt')
print(a)
=================================
how are you ?
0
os.popen() 方法,可以实现一个“管道”,从这个命令获取的值可以在python 中继续被使用
语法
popen()方法语法格式如下:
os.popen(command[, mode[, bufsize]])
参数
command – 使用的命令。
mode – 模式权限可以是 ‘r’(默认) 或 ‘w’。
bufsize – 指明了文件需要的缓冲大小:0意味着无缓冲;1意味着行缓冲;其它正值表示使用参数大小的缓冲(大概值,以字节为单位)。负的bufsize意味着使用系统的默认值,一般来说,对于tty设备,它是行缓冲;对于其它文件,它是全缓冲。如果没有改参数,使用系统的默认值。
返回值
返回一个文件描述符号为fd的打开的文件对象
import os
command ='adb shell ls -lh /sdcard/tmp/screenshot/'
a = os.popen(command, 'r' ,1)
print(a)
=============================
三种方式
import os
command ='adb shell ls -lh /sdcard/tmp/screenshot/'
a = os.popen(command, 'r' ,1).read()
print(a)
========================
total 4.0K
-rw-rw---- 1 root sdcard_rw 14 2021-12-20 23:23 1.txt
import os
command ='adb shell ls -lh /sdcard/tmp/screenshot/'
a = os.popen(command, 'r' ,1).readline()
print(a)
===================
total 4.0K
import os
command ='adb shell ls -lh /sdcard/tmp/screenshot/'
a = os.popen(command, 'r' ,1).readlines()
print(a)
================================
['total 4.0K\n', '-rw-rw---- 1 root sdcard_rw 14 2021-12-20 23:23 1.txt\n']
补充:read()/readline()/readlines()区别
方法 | 类型 | 返回文本 |
---|---|---|
read() | str | 以原格式返回全部文本 |
readline() | str | 只返回第一行文本 |
readlines() | str | 以原格式返回全部文本 |
也可以选择读取第几行linecache 模块 |
file_path = r'C:\Users\Administrator\Desktop\test.txt'
a = linecache.getline(file_path,2)
print(a)
=====================
12232
command ='adb shell ls -lh /sdcard/tmp/screenshot/'
file_path = r'C:\Users\Administrator\Desktop\test.txt'
a = linecache.getlines(file_path,2)
print(a)
==============================
['\n', '12232\n', '\n', 'aaf\n', 'd\n', 'aaf\n', '\n', 'df\n', 'aaf\n', 'dfa\n']
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)
args:表示要执行的命令。必须是一个字符串,字符串参数列表。
stdin、stdout 和 stderr:子进程的标准输入、输出和错误。其值可以是 subprocess.PIPE、subprocess.DEVNULL、一个已经存在的文件描述符、已经打开的文件对象或者 None。subprocess.PIPE 表示为子进程创建新的管道。subprocess.DEVNULL 表示使用 os.devnull。默认使用的是 None,表示什么都不做。另外,stderr 可以合并到 stdout 里一起输出。
timeout:设置命令超时时间。如果命令执行时间超时,子进程将被杀死,并弹出 TimeoutExpired 异常。
check:如果该参数设置为 True,并且进程退出状态码不是 0,则弹 出 CalledProcessError 异常。
encoding: 如果指定了该参数,则 stdin、stdout 和 stderr 可以接收字符串数据,并以该编码方式编码。否则只接收 bytes 类型的数据。
shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令。
注意:
run 方法调用方式返回 CompletedProcess 实例,和直接 Popen 差不多,实现是一样的,实际也是调用 Popen,与 Popen 构造函数大致相同
ret.returncode == 0 代表执行成功
import subprocess
command= "adb shell ls -lh"
ret = subprocess.run(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding="utf-8",timeout=1)
if ret.returncode == 0:
print("success:",ret)
else:
print("error:",ret)
========================
success: CompletedProcess(args='adb shell ls -lh', returncode=0, stdout='ls: ./version.prop: Permission denied\nls: ./verity_key: Permission denied\nls: ./ueventd.rc: Permission denied\n)
if ret.returncode == 0:
print("success:",ret.stdout)
else:
print("error:",ret.stderr)
=======================
uccess: ls: ./version.prop: Permission denied
ls: ./verity_key: Permission denied
ls: ./ueventd.rc: Permission denied
ls: ./rootscan.conf: Permission denied
ls: ./resetFactory.cfg: Permission denied
Popen 是 subprocess的核心,子进程的创建和管理都靠它处理。
构造函数:
class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False,
startupinfo=None, creationflags=0,restore_signals=True, start_new_session=False, pass_fds=(),
*, encoding=None, errors=None)
常用参数:
args:shell命令,可以是字符串或者序列类型(如:list,元组)
bufsize:缓冲区大小。当创建标准流的管道对象时使用,默认-1。
0:不使用缓冲区
1:表示行缓冲,仅当universal_newlines=True时可用,也就是文本模式
正数:表示缓冲区大小
负数:表示使用系统默认的缓冲区大小。
stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
preexec_fn:只在 Unix 平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令。
cwd:用于设置子进程的当前目录。
env:用于指定子进程的环境变量。如果 env = None,子进程的环境变量将从父进程中继承。
单行命令执行
command ='ls -lh /sdcard/tmp/screenshot/'
pipe = subprocess.Popen('adb shell '+command,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,shell=True)
curline= pipe.stdout.readlines()
if curline !='':
print(curline)
==============================
[b'total 4.0K\r\n', b'-rw-rw---- 1 root sdcard_rw 14 2021-12-20 23:23 1.txt\r\n']
import subprocess
def cmd(command):
subp = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding="utf-8")
subp.wait(2)
if subp.poll() == 0:
print(subp.communicate()[1])
else:
print("失败")
cmd("java -version") # 相当于 adb shell java -version
===========================
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)
import subprocess
cmds = [r’cd /sdcard/data’,r’cat 1.txt’]
pipe = subprocess.Popen(“adb shell “,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
out,err = pipe.communicate((”\n”.join(cmds)+“\n”).encode(“UTF-8”))
print(out,err)