掘金 后端 ( ) • 2024-04-09 09:56

背景描述

本文要讲述的东西比较简单,是在python中对excel的一些处理,主要是从线上的服务器拿到文件的流,然后用openpyxl 操作该流,最后整理完毕后重新上传上去服务器中给别人用,简单来说就是生成自己的excel上传上去。

openpyxl

openpyxl是一个用于处理Excel文件的Python库。它提供了丰富的功能,使得用户能够轻松地读取、写入和操作Excel文件,而不需要依赖于Microsoft Excel软件。作为一个开源项目,openpyxl在Python生态系统中得到了广泛的应用,成为处理Excel数据的首选工具之一。

即然知道了使用openpyxl做我们的工作,那么文档就必不可少,而对于excel文件,我们也需要了解一些基本知识,比如一个excel文件的组成,是由一个或多个sheet构成的,可以将sheet理解为一个又一个表,接着每个sheet中才是我们的表格。

读取xlsx流

response = s3_client.get_object(
  Bucket=bucket,
  Key="input_sample.xlsx"
)
bio = io.BytesIO(response["Body"].read())

上面的代码中,使用bio去读取到了文件的流。

接下来,我们直接使用openpyxl的load_workbook读取到我们的文件

wb = load_workbook(bio, read_only=True)

因为load_workbook可以读取到流,所以省了我们去download文件到本地的操作。

接下来,是我们要操作每个sheet

worksheets = wb.worksheets
​
for worksheet in tqdm(worksheets):
  bio.seek(0)
  obj["inputs"][worksheet.title] = pd.read_excel(
      bio, sheet_name=worksheet.title
  )
​
wb.close()
bio.close()

​ 上方的代码中,遍历了每一个sheet,拿到了文件之后,我们使用pandas去操作,无它,这个方法最方便,而且pandas使用的人多。 最后的最后,请不要忘记关闭我们的流以及workbook,不然被人骂不关我事。

到了这儿,我们的读取已经完成了,你的操作可以在obj上去实施了。

上传xlsx​

在生成流文件并且上传的过程中,最麻烦的一点是如何不在本地生成一个缓存文件,而幸运的是我可以通过bio来操作,这对我这个新手来说真的是再次节约了不少时间。 首先,我们依旧需要生成一个载体,我们的workbook。​

 wb = Workbook()

接下来呢,生成一个sheet

 BCSheet = wb.create_sheet("TTLBC")

需要注意的是,create_sheet的时候,如果不传入下标,会自动排序生成。也就是说在第一个默认的sheet之后,才会使下面这个TTLBC的sheet,如果想要生成指定位置的sheet,需要使用下面的语法

 BCSheet = wb.create_sheet("TTLBC",0)

由于我们create这个sheet的时候,也返回了一个sheet的实体(我也不知都这么说对不对),所以我们下面不需要直接再去使用wb.sheets['sheetname']这种方式去找到那个sheet。

接下来,要怼数据进去了,部分人喜欢用cell级别的操作,而我更喜欢用append来操作每一个row,所以我会选择用下面的方式去操作

 BCSheet.append([v.strftime("%Y-%m-%d") for v in x])

不需要管中间那段麻烦的代码,只要看到中括号就可以知道我丢进去的是一个List。

最后,重头戏来了,上传到s3之前,我们需要先做些转换,查找了一些文档,才知道可以用bio转化

temp_file = io.BytesIO()
wb.save(temp_file)
temp_file.seek(0)

生成的是一个temp,所以不会本地生成临时文件,真的是太赞了!

ok,最后再看你的方法,我直接上传到s3

s3_client.put_object(
  Bucket=bucket,
  Key="Dtest.xlsx",
  Body=temp_file,
)
​

求关注,希望能帮到你~

公众号文章