1.dobbo操作
封装模块:Telnetlib的telnet类是一个关于telnet协议的类。
telnet协议:是一个远程终端协议,tcp/ip协议的一员,属于应用层。
作用:可以在本地计算机,通过网络进入另一个电脑。
交互过程:使用telnet进入远程算计系统,启动2个程序:本地主机:telnet客户端程序;远程主机:telnet服务器程序
python实现telnet客户端主要功能:(1)连接主机(2)执行命令
封装思路:
1.创建telnet对象,连接主机
2.执行命令
3.退出机器,关闭连接
使用场景:
执行dubbo命令
class Dubbo:
def __init__(self, connections: tuple):
"""
连接主机
:param connections: host, port
"""
self.tn = telnetlib.Telnet(*connections)
def __del__(self):
# 退出机器
self.tn.write(b'quit\n')
# 关闭连接
self.tn.close()
def do(self, command_str):
# 执行命令
print(datetime.now().strftime('%Y-%m-%d %H:%M:%S %f')[:-3])
print('【执行命令】:', command_str)
self.tn.write(command_str.encode() + b'\n')
# 在IO不阻塞的情况下读取所有的数据,否则返回空
time.sleep(2)
data = self.tn.read_very_eager()
# 解码返回的数据
print('返回结果:', data.decode())
return data.decode()
2.excel
import openpyxl
def excel_handler(filename, sheetname):
"""
处理excel数据
:param filename: excel路径
:param sheetname: excel sheetname
:return:
"""
# 打开excel
wb = openpyxl.load_workbook(filename)
# sheet
ws = wb.active
if sheetname:
ws = wb[sheetname]
row_list = list(ws.rows)
# 表头
headers = [row.value for row in row_list[0]]
# 生成[{},{}]形式
case_list = []
for row in row_list[1:]:
case_list.append(dict(zip(headers, [cell.value for cell in row])))
return case_list
3.日志
import logging
import colorlog
from logging.handlers import TimedRotatingFileHandler
def get_logger(name, filename, when='s', interval=1, backupCount=1, encoding='utf-8', debug=True, fmt=None):
"""
打印日志
:param name: 日志器名称
:param filename: 日志保存文件名
:param when: 时间单位
:param interval: 间隔时间
:param backupCount: 循环
:param encoding:
:param debug:
:param fmt:
:return:
"""
# 1创建日志器
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
# 处理参数
if debug:
file_level = logging.DEBUG
console_level = logging.DEBUG
else:
file_level = logging.WARN
console_level = logging.INFO
if fmt is None:
fmt = '%(levelname)s %(asctime)s [%(filename)s-->line:%(lineno)d]:%(message)s'
# 2.创建日志处理器
file_handle = TimedRotatingFileHandler(filename, when=when, interval=interval, backupCount=backupCount, encoding=encoding)
file_handle.setLevel(file_level)
console_handle = logging.StreamHandler()
console_handle.setLevel(console_level)
# 3. 创建格式化器
# 文件格式化器
file_formatter = logging.Formatter(fmt=fmt)
# 控制台的格式化器
log_colors_config = {
'DEBUG': 'white', # cyan white
'INFO': 'cyan',
'WARNING': 'green',
'ERROR': 'bold_red',
}
console_formatter = colorlog.ColoredFormatter(
fmt='%(log_color)s'+fmt,
log_colors=log_colors_config)
# 4.添加格式化器
file_handle.setFormatter(file_formatter)
console_handle.setFormatter(console_formatter)
# 5.添加日志处理器
logger.addHandler(file_handle)
logger.addHandler(console_handle)
return logger
4.requests请求
def req(url, headers, method='post', if_print=True, **kargs):
"""
发请求:如果出现异常会循环请求|响应为403,会循环请求3次
:param url:
:param headers:
:param method:
:param res_type: 响应类型
:param kargs: 请求其他参数:dict
:return:
"""
i = 0
while i < 3:
try:
logger.debug('============URL============')
logger.debug(url)
logger.debug('============method============\n{}'.format(method))
logger.debug('============headers============\n{}'.format(headers))
if if_print is True:
for key, value in kargs.items():
logger.debug('============{}============\n{}'.format(key.lower(), value))
logger.debug('============请求时间============\n{}'.format(time.strftime('%Y-%m-%d %H:%M:%S')))
res = getattr(requests, method)(url=url, headers=headers, **kargs)
logger.debug('============响应状态码============\n{}'.format(res.status_code))
logger.debug('============响应结果============\n{}'.format(res.text))
if res.status_code == 403:
logger.info('响应状态码为403')
i += 1
continue
except requests.exceptions.RequestException as e:
logger.error(e)
logger.info('错误次数:{}'.format(i))
i += 1
else:
return res
5.文件操作
import copy
import os
class FileOperation:
def write_file(self, file_path, content):
"""写文件"""
with open(file_path, 'wb') as file:
file.write(content)
def read_file(self, file_path):
"""读取文件"""
with open(file_path, 'rb') as file:
content = file.read()
return content
def copy_file(self, file_path):
"""复制文件"""
copy_file = copy.deepcopy(self.read_file(file_path))
return copy_file
def get_file_path(self, file_name, if_material_path=True):
"""获取文件路径"""
parent_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
material_path = 'file/material_file' if if_material_path is True else 'file/tempory_file'
return os.path.join(parent_path, material_path, file_name)
6.subprocess封装
subprocess模块:类似系统的cmd,执行系统命令,启动进程,并且连接到他们的输入输出管道,从而获取返回值
subprocess的Popen类:创建一个进程,传入的命令类型:str/list,
eg:adb devices/[adb,devices]。但是前者如果shell=False,不会工作;如果是True,则相当于subprocess.Popen(["/bin/sh", "-c", "cat test.txt"]),会正常处理
Popen.communicate():和进程交互,发送命令,从stdout和stderr读取数据并返回
如果需要传入的命令,命令类型:byte or string。
封装思路:
1.执行命令,创建子进程
2.和进程交互,(执行命令,可选),获取返回stdout和stder
3.执行完命令结束进程
import subprocess
def execute_shell_str(cmd):
"""启动进程,执行命令
cmd:str/list: adb devices/[adb,devices],适用于单个命令
"""
print(cmd)
# 创建子进程
# Popen()类中,cmd:字符串或者列表 "cat test.txt" 或者 ["cat","test.txt"],
# 但是前者如果shell=False,不会工作;如果是True,则相当于subprocess.Popen(["/bin/sh", "-c", "cat test.txt"]),会正常处理
obj = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True) # A string
try:
# 与进程交互
stdout, stderr = obj.communicate()
print("当前执行进程号为:{}".format(obj.pid))
print('===stdout===', stdout.decode('gbk'), stderr.decode('gbk'))
return stdout.decode()
except Exception as e:
raise e
finally:
# 结束进程号
obj.kill()
print(f"当前返回状态:{obj.poll()}") # 0:正常结束;1:异常
def execute_shell(cmd):
"""启动进程,执行完整的命令,适用于多条命令
cmd:str/list
eg:
cmd="adb devices"
cmd = [
"adb devices",
"where adb" # 这是是非常关键的,退出
]
"""
print(cmd)
cmd = [cmd] if type(cmd) is str else cmd
for i in cmd:
print('cmd===', i)
obj = subprocess.Popen(i, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True) # i:A string
stdout, stderr = obj.communicate()
print(stdout.decode(), stderr.decode('gbk'))
# 结束进程号
obj.kill()
print(f"当前返回状态:{obj.poll()}\n") # 0:正常结束;1:异常
def adb_shell(cmds):
"""
进入某个环境执行语句(adb shell),命令用列表方式全部列出,,适用于执行adb shell命令
注意:1.shell内部命令需要带\n,执行完后一定记得执行exit命令退出,否则会阻塞
2.有些路径下执行命令需要有root权限
cmds = [
"cd data",
'cd data',
"ls",
"exit",#这是是非常关键的,退出
]
"""
print(cmds)
# 进入某个环境(adb shell)
obj = subprocess.Popen("adb shell", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE) # A string, or a sequence of program arguments.
# 在adb shell环境下执行命令
stdout, stderr = obj.communicate(("\n".join(cmds) + "\n").encode()) # byte or string; Send data to stdin
print(stdout.decode('gbk'), stderr.decode('gbk'))
return stdout.decode('gbk')
tips:在windows执行adb shell命令查看目录下文件:ll;但是使用python调用adb命令需要用ls