一、表格读写
所有可使用的表格读写库 Python Resources for working with Excel - Working with Excel Files in Python
1、excel表格读取 使用xlrd
# _*_ conding:utf-8 _*_
import xlrd
book = xlrd.open_workbook("./a.xlsx") # 读取表格文件
print(book.sheet_names()) # 所有的sheet的名字
# sheet = book.sheet_by_name('Sheet1') # 通过sheet名获取指定sheet数据
sheet = book.sheet_by_index(0) # 通过sheet下标获取指定sheet数据
print(sheet.name) # sheet名
print(sheet.nrows) # 指定sheet的总行数
print(sheet.ncols) # 指定sheet的总列数
# 按行输出
for r in range(sheet.nrows):
print(sheet.row(r)) # 第几行
# # 按列输出
for i in range(sheet.ncols):
print(sheet.col(i)) # 第几列
print(sheet.row_values(rowx=0, start_colx=0, end_colx=-1)) # 第几行内 从第几列开始到第几列结束
print(sheet.row_values(rowx=sheet.nrows-1, start_colx=0, end_colx=-1)) # 第几行内 从第几列开始到第几列结束
print(sheet.cell_value(rowx=0, colx=0)) # 第几行 第几列的值
print(sheet.cell(rowx=2, colx=1)) # 第几行 第几列的某个值的类型和具体数值
print(sheet.row_len(rowx=1)) # 指定行数的字段数量
print(sheet.col(colx=0, start_rowx=0, end_rowx=-1)) # 指定列的类型及具体值 [text:'类目', text:'一年级', text:'二年级']
print(sheet.col_values(colx=0, start_rowx=0, end_rowx=sheet.row_len(rowx=0)+1)) # 指定列的指定行范围数据
2.excel表格写 使用 openpyxl库
官方文档:openpyxl - A Python library to read/write Excel 2010 xlsx/xlsm files — openpyxl 3.0.9 documentation
# _*_ coding:utf-8 _*_
import openpyxl
wb = openpyxl.Workbook()
sheet1 = wb.active
sheet1.title = "test" # sheet名
sheet1['C5'] = "张三" # 指定位置赋值
sheet2 = wb.create_sheet(title="test1") # 创建sheet
sheet2['A1'] = '小明'
sheet2.cell(row=2, column=1, value='测试') # 指定位置赋值
wb.save(filename="b.xlsx") # 保存
方法封装
#! /usr/bin/python3
# -*- coding: utf-8 -*-
# @Time: 2022/2/22 14:21
# @Author: 一碗烈酒
import openpyxl
import os
class ExcelUtil:
def __init__(self, file_name: str, mode: str = "r"):
"""
:param file_name: 文件路径
:param mode: 模式。 r: 读文件; w:写文件
"""
# 文件前置处理
self.file_name = self._file_preprocess(file_name)
if mode == "w":
self._create_new_excel(self.file_name)
self.work_book = openpyxl.load_workbook(self.file_name)
def _file_preprocess(self, file_name: str, mode: str = "r"):
"""
文件前置处理。修正文件后缀名;目录不存在则创建目录,文件不存在则创建一各空的表格
:param file_name: 文件路径
:param mode: 是读取文件还是写入文件 :r, w
:return: 文件绝对路径
"""
# 将文件路径转换为绝对路径,防止因为平台不同导致路径分隔符不一致的问题
file_name = os.path.abspath(file_name)
# 检查文件后缀名是否正确
if os.path.splitext(file_name)[-1] != ".xlsx":
if mode == "r":
# 方案一:直接抛异常
raise NameError("文件后缀名不正确!需要 .xlsx 但是提供了 {}".format(os.path.splitext(file_name)[-1]))
if mode == "w":
# 方案二:修改正确的文件后缀名
file_name = os.path.join(os.path.split(file_name)[0],
os.path.splitext(os.path.split(file_name)[-1])[0] + ".xlsx")
# # 检查目录是否存在,不存在则新建
# if not os.path.exists(os.path.split(file_name)[0]):
# os.makedirs(os.path.split(file_name)[0])
# # 检查文件是否存在,不存在,创建一个空的文件
# if not os.path.exists(file_name):
# self._create_new_excel(file_name)
return file_name
def _create_new_excel(self, file_name: str, default_sheet_name: str = "Sheet"):
"""
创建一个空的Excel文件
:param file_name: 文件名,包含路径
:param default_sheet_name: 默认sheet名
:return: 创建成功返回True, 创建失败返回 False
"""
# 检查目录是否存在,不存在则新建
if not os.path.exists(os.path.split(file_name)[0]):
os.makedirs(os.path.split(file_name)[0])
# 检查文件是否存在,不存在,创建一个空的文件
if not os.path.exists(file_name):
self._create_new_excel(file_name)
# 新建并保存excel
new_workbook = openpyxl.Workbook()
default_sheet = new_workbook.active
default_sheet.title = default_sheet_name
new_workbook.save(file_name)
return True
def get_sheetnames(self):
"""
读取文件的 sheet名列表
:param file_name: 文件路径
:return: sheet名列表
"""
return self.work_book.sheetnames
def get_sheet_data_row_by_row(self, sheet_name: str, rows: str = "all"):
"""
逐行读取Excel文件,返回指定sheet下的全部数据。
:param sheet_name: sheet名
:return: 全部数据。包括 (表头[]和数据[[], []])
"""
sheet = self.work_book[sheet_name]
values = []
if rows == "all":
rows = sheet.max_row
cols = sheet.max_column
for row in range(1, rows + 1):
rows_value = []
for col in range(1, cols + 1):
rows_value.append(sheet.cell(row, col).value)
values.append(rows_value)
return values[0], values[1:]
def get_column_data(self, sheet_name: str, column: int, start_row: int = 2):
"""
读取第几列的数据
:param sheet_name: 指定sheet名称
:param col: 指定第几列
:param start: 从第几行开始读取,默认第二行
:return: list格式指定列的数据
"""
cols = []
sheet = self.work_book[sheet_name]
for i in range(start_row, sheet.max_row + 1):
cols.append(sheet.cell(i, column).value)
return cols
def get_row_data(self, sheet_name: str, row: int, start_column: int = 2):
"""
读取第几行的数据
:param sheet_name: 指定sheet名称
:param row: 指定第几行
:param start_column: 从第几列开始读取,默认第二列
:return: list格式指定行的数据
"""
rows = []
sheet = self.work_book[sheet_name]
for col in range(start_column, sheet.max_column + 1):
rows.append(sheet.cell(row, col).value)
return rows
def get_all_rows(self, sheet_name: str, start_column: int = 2):
"""
逐行读取数据,返回全部数据。读取指定sheet的数据,默认从第二列开始读取
:param sheet_name: sheet名
:param start_column: 开始读取的列,默认从第二列开始读取
:return: [[],[]] 逐行读取的数据列表
"""
datas = []
for row in range(start_column, self.work_book[sheet_name].max_row + 1):
datas.append(self.get_row_data(sheet_name, row, start_column))
return datas
def get_all_columns(self, sheet_name: str, start_row: int = 2):
"""
逐列读取数据,返回全部数据,读取指定sheet的数据,默认从第二行开始读取
:param sheet_name: sheet名
:param start_row: 开始读取的行,默认从第二行开始读取
:return: [[],[]] 伫列读取的数据列表
"""
columns = []
sheet = self.work_book[sheet_name]
for i in range(start_row, sheet.max_row + 1):
columns.append(self.get_column_data(sheet_name, i, start_row))
return columns
def write_new_excel_row_by_row(self, sheet_name: str, row_values: list):
"""
写入数据到一个新的表格中。
:param sheet_name: sheet名
:param row_values: 数据 格式:[[row1column1, row1column2, row1column3], [row2column1, row2column2, row2column3], [row3column1, row3column2, row3column3], ]
:return:
"""
worksheet = self.work_book[sheet_name]
worksheet.title = sheet_name
for row in row_values:
worksheet.append(row)
self.work_book.save(self.file_name)
return True
if __name__ == "__main__":
# 读文件
## excel = ExcelUtil("./aaa/bbb/tmp11.xlsxss") # 这个会报错,因为默认实例是读取文件,然而文件后缀又不对,所以会抛异常
excel_read = ExcelUtil("tmp.xlsx", mode="r")
print(excel_read.get_sheetnames())
print(excel_read.get_row_data(excel_read.get_sheetnames()[0], row=1, start_column=1))
print(excel_read.get_column_data(excel_read.get_sheetnames()[0], column=1, start_row=1))
print(excel_read.get_all_rows(excel_read.get_sheetnames()[0], start_column=1))
print(excel_read.get_all_columns(excel_read.get_sheetnames()[0], start_row=1))
print(excel_read.get_sheet_data_row_by_row(excel_read.get_sheetnames()[0]))
# 写文件
# excel_writer = ExcelUtil("tmp.xlsx", mode="w")
# excel_writer.write_new_excel_row_by_row(sheet_name=excel_writer.get_sheetnames()[0], row_values=[[1, 2, 3], [4, 5, 6]])
二、TXT文件读写
# 读写模式:w:写入新文件,r:读取已有文件,wb:二进制写入,rb:二进制读取,a+:追加,
# 写入文件
with open("./c.txt", "a+", encoding="utf-8") as f:
f.write("\n你是我的小呀小苹果\thaha")
# 读取文件
with open("./c.txt", "r", encoding="utf-8") as f:
print(f.read()) # 读取所有值,作为一个字符串返回
# print(f.readline()) # 读取一行值,再次调用时从本次读取位置继续下一行读取
# print(f.readlines()) # 读取所有值 列表格式,每行一个字符串
三、csv文件读写
csv 方法 封装
import csv
import codecs
class Csv:
def __init__(self, filename):
self.filename = filename
def write_dict(self, field_titles, values):
"""
将字典格式的数据列表写入到csv文件
:param field_titles: 文件表头 格式:可迭代对象均可 示例:["id", "name"]
:param values: 文件数据 格式:[{}, {}] 示例:[{"id": 1, "name": "a"}, {"id": 2, "name": "b"}]
:return: True
"""
with open(self.filename, "w", encoding="utf-8", newline="") as f: # newline="" 表头和数据之间不空行
writer = csv.DictWriter(f, fieldnames=field_titles)
writer.writeheader()
for row_dict in values:
writer.writerow(rowdict=row_dict)
return True
def write_iterative(self, values):
"""
将可迭代格式的数据列表写入到csv文件
:param values: 文件数据 示例:[("id", "name"), (1, "张三"), (2, "李四")]
:return: True
"""
with codecs.open(self.filename, "w", encoding="utf-8") as f: # newline="" 表头和数据之间不空行
writer = csv.writer(f)
writer.writerows(values)
return True
def read_values(self, list=True, dict=False):
"""
读取csv文件内的所有数据,可选返回列表格式和字典格式
:param list: 返回数据为列表嵌套列表格式, 默认返回此类型
:param dict: 返回数据为列表嵌套字典格式
:return: 数据列表
"""
values = []
with open(self.filename, "r", encoding="utf-8") as f:
if list:
for value in csv.reader(f):
values.append(value)
elif dict:
# 以下两种方式读取都可以用 csv.reader(f), csv.DictReader(f)
# for value in csv.reader(f):
for value in csv.DictReader(f):
values.append(value)
return values
def read_list_values(self):
"""
读取csv文件全部数据,返回列表嵌套格式的数据,同 read_values() 方法返回结果一致
:return: 列表嵌套格式的数据
"""
values = []
with open(self.filename, "r", encoding="utf-8") as f:
for value in csv.reader(f):
values.append(value)
return values
if __name__ == "__main__":
c = Csv("./csv_tmp.csv")
c.write_dict(field_titles=("id", "name"), values=[{"id": 1, "name": "a"}, {"id": 2, "name": "b"}, ])
# c.write_iterative(values=[("id", "name"), (1, "张三"), (2, "李四")])
print(c.read_values())
print(c.read_list_values())
四、yaml 格式读写
输出结果:
import yaml
import os
import jsonpath
class YamlUtil:
"""
yaml文件操作基础方法
"""
def read_yaml(self, path):
"""
从yaml文件内读取全部数据,文件内的key不能重复,否则读取最后一个
:param path:
:return:
"""
with open(file=path, mode="r", encoding="utf-8") as f:
yaml_data = yaml.load(f, Loader=yaml.BaseLoader)
return yaml_data
def read_yaml_by_key(self, path, key, index=0):
"""
从 yaml 文件中读取指定 key 的数据 如果没有找到 jsonpath 方法会返回 False
jsonpath http://goessner.net/articles/JsonPath
:param path:
:param key: 要查找的 key
:param index: 找到符合条件数据列表的下标,默认为第一条数据
:return: 对应 key 的值,没有找到返回 False
"""
result = jsonpath.jsonpath(self.read_yaml(path), f"$..{key}")
if not result:
return result
else:
return result[index]
def write_yaml(self, path, value):
"""
往yaml文件内追加写入
:param path:
:param data:
:return:
"""
with open(file=path, mode="a", encoding="utf-8") as f:
yaml.dump(data=value, stream=f, allow_unicode=True)
def change_yaml_value(self, path, key, value):
"""
修改yaml文件内某个具体key的value值。没有指定的key就追加。
:param path:
:param key: 需要修改的 key
:param value: 需要修改的 key 的值
:return:
"""
yaml_data = self.read_yaml(path=path)
if yaml_data:
yaml_data[key] = value
else: # 文件内容为 None
yaml_data = {key: value}
# 先清除原有数据再把修改后的数据写入到文件
self.clear_yaml(path=path)
self.write_yaml(path=path, value=yaml_data)
def clear_yaml(self, path):
"""
清空yaml文件内容
:param path:
:return:
"""
with open(file=path, mode="w", encoding="utf-8") as f:
f.truncate()
def yaml_full_file(self, loader, node):
""" 构造器函数。需要配合 add_construct 方法一起使用。用来读取某个yaml文件内的全部内容 """
# print(loader.name, node.value, node.tag)
file_name = os.path.join(os.path.dirname(loader.name), node.value) # 引用文件名
return self.read_yaml(file_name)
def yaml_value_by_key(self, loader, node, key):
""" 构造器函数。需要配合 add_construct 方法一起使用。用来读取某个yaml文件内指定 key 的值 """
file_name = os.path.join(os.path.dirname(loader.name), node.value) # 引用文件名
# return jsonpath.jsonpath(self.read_yaml(file_name), f"$..{key}")[0]
return self.read_yaml_by_key(file_name, key)
def add_construct(self, tag, func_name):
""" 添加/注册自定义的构造器 """
yaml.add_constructor(tag, func_name)
if __name__ == '__main__':
# aaa = "./aaa.yml"
# YamlUtil().clear_yaml(path=aaa)
# YamlUtil().write_yaml(path=aaa, data={"desc": "娃哈哈"})
# YamlUtil().write_yaml(path=aaa, data={"name": "张三"})
# YamlUtil().write_yaml(path=aaa, data={"age": "10", "score": 99})
# data = YamlUtil().read_yaml(path=aaa)
# print(data)
# YamlUtil().change_yaml_value(path=aaa, key="score", value=100)
# YamlUtil().change_yaml_value(path=aaa, key="name", value="李四")
# YamlUtil().change_yaml_value(path=aaa, key="desc", value="柴可夫斯基")
# YamlUtil().change_yaml_value(path=aaa, key="class", value="小六")
# data = YamlUtil().read_yaml(path=aaa)
# print(data)
pass
yaml 自定义构造器 在yaml文件内引用Python函数
import yaml
import time
import os
import jsonpath
"""
yaml 自定义构造器,可以在yaml文件中使用自定义构造器,然后调用外部文件或者Python方法
"""
def get_time():
print(time.time())
return time.time()
def yaml_full_file(loader, node):
""" 构造器函数。用来读取某个yaml文件内的全部内容 """
# print(loader.name, node.value, node.tag)
file_name = os.path.join(os.path.dirname(loader.name), node.value) # 引用文件名
with open(file_name, encoding="utf-8") as f:
return yaml.load(f, Loader=yaml.FullLoader)
def yaml_value_by_appversion(loader, node, key="appVersion", index=0):
""" 构造器函数。用来读取某个yaml文件内指定 key 的值 """
file_name = os.path.join(os.path.dirname(loader.name), node.value) # 引用文件名
with open(file_name, encoding="utf-8") as f:
data = yaml.load(f, Loader=yaml.FullLoader)
return jsonpath.jsonpath(data, f"$..{key}")[index]
def yaml_value_by_auth(loader, node, key="Authorization", index=0):
""" 构造器函数。用来读取某个yaml文件内指定 key 的值 """
file_name = os.path.join(os.path.dirname(loader.name), node.value) # 引用文件名
with open(file_name, encoding="utf-8") as f:
data = yaml.load(f, Loader=yaml.FullLoader)
return jsonpath.jsonpath(data, f"$..{key}")[index]
def yaml_value_by_host(loader, node, key="Host", index=0):
""" 构造器函数。用来读取某个yaml文件内指定 key 的值 """
file_name = os.path.join(os.path.dirname(loader.name), node.value) # 引用文件名
with open(file_name, encoding="utf-8") as f:
data = yaml.load(f, Loader=yaml.FullLoader)
return jsonpath.jsonpath(data, f"$..{key}")[index]
if __name__ == '__main__':
# 添加自定义构造器
yaml.add_constructor("!include", yaml_full_file)
yaml.add_constructor("!appVersion", yaml_value_by_appversion)
yaml.add_constructor("!auth", yaml_value_by_auth)
yaml.add_constructor("!host", yaml_value_by_host)
# 读取数据
datas = yaml.load(stream=open("a.yml", mode="r", encoding="utf-8"), Loader=yaml.FullLoader)
# print(datas['headers'])
print(datas.get("headers"))
print(datas.get("body_json"))
# a.yml
headers:
User-Agent: "OkHttp Headers.java"
Accept: "*/*"
Accept-Encoding: ""
Content-Type: "application/json; charset=utf-8"
Authorization: !auth b.yml
Host: !host b.yml
body_json:
imei: ""
appVersion: !appVersion b.yml
# b.yml
headers:
Authorization: "aaaaaa_bbbbbbb"
Host: "www.baidu.com"
body:
appVersion: "1.0"
userid: "100000"
五、其他
adb 手机设备信息读取
import subprocess
from icecream import ic
def read_usb_device_info():
"""
获取当前usb链接的单一手机的设备号,安卓系统版本
:return: {'deviceName': 'device id', 'platformVersion': 'android version'}
"""
devicename_platformversion = {}
def get_adb_result(command):
"""
获取cmd命令行返回结果
:param command: 命令行命令
:return:
"""
result = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE).stdout.read()
return str(result).strip().replace("\\r", "").replace("\\n", "").replace("b", "").replace("'", "")
try:
# 获取设备id
devices = get_adb_result("adb devices")
# 获取安卓系统版本
android_version = get_adb_result("adb shell getprop ro.build.version.release")
# 获取干净的设备id
devices = devices.split(" ")[-1].split("\\")[0].replace("attached", "")
devicename_platformversion = {"deviceName": devices, "platformVersion": android_version}
except Exception as e:
devicename_platformversion = {}
finally:
ic(devicename_platformversion)
return devicename_platformversion