在 Python3 中压缩写入 StringIO 缓冲区的 CSV 文件
Compress a CSV file written to a StringIO Buffer in Python3
我正在将 pdf 文件中的文本解析为有序字符元数据行;我需要将这些文件序列化到云存储,一切正常,但由于它们的大小,我也想 gzip 这些文件,但我 运行 遇到了一些问题。
这是我的代码:
import io
import csv
import zlib
# This data file is sent over Flask
page_position_data = pdf_parse_page_layouts(data_file)
field_order = ['char', 'position', 'page']
output_buffer = io.StringIO()
writer = csv.DictWriter(output_buffer, field_order)
writer.writeheader()
for page, rows in page_position_data.items():
for text_char_data_row in rows:
writer.writerow(text_char_data_row)
stored_format = zlib.compress(output_buffer)
这会成功地将每一行读入 io.StringIO 缓冲区,但是 gzip/zlib 似乎只适用于类似字节的对象,例如 io.BytesIO 所以最后一行错误;我无法创建将 csv 读入 BytesIO 缓冲区,因为 DictWriter/Writer 错误,除非使用 io.StringIO()。
感谢您的帮助!
我想通了,想向遇到此问题的任何人展示我的答案:
问题是 zlib.compress 需要一个类似字节的对象;这实际上并不意味着 StringIO 或 BytesIO,因为它们都是 "file-like" 实现 read() 和普通 unix 文件句柄的对象。
要解决此问题,您只需使用 StringIO() 写入 csv 文件,然后调用从 StringIO() 对象中获取字符串并将其编码为字节串;然后它可以被 zlib 压缩。
import io
import csv
import zlib
# This data file is sent over Flask
page_position_data = pdf_parse_page_layouts(data_file)
field_order = ['char', 'position', 'page']
output_buffer = io.StringIO()
writer = csv.DictWriter(output_buffer, field_order)
writer.writeheader()
for page, rows in page_position_data.items():
for text_char_data_row in rows:
writer.writerow(text_char_data_row)
encoded = output_buffer.getvalue().encode()
stored_format = zlib.compress(encoded)
对于任何感兴趣的人,我有一个替代答案,应该使用较少的中间 space,它需要 python 3.3 及以上才能使用 getbuffer()
方法:
from io import BytesIO, TextIOWrapper
import csv
import zlib
def compress_csv(series):
byte_buf = BytesIO()
fp = TextIOWrapper(byte_buf, newline='', encoding='utf-8')
writer = csv.writer(fp)
for row in series:
writer.writerow(row)
compressed = zlib.compress(byte_buf.getbuffer())
fp.close()
byte_buf.close()
return compressed
我正在将 pdf 文件中的文本解析为有序字符元数据行;我需要将这些文件序列化到云存储,一切正常,但由于它们的大小,我也想 gzip 这些文件,但我 运行 遇到了一些问题。
这是我的代码:
import io
import csv
import zlib
# This data file is sent over Flask
page_position_data = pdf_parse_page_layouts(data_file)
field_order = ['char', 'position', 'page']
output_buffer = io.StringIO()
writer = csv.DictWriter(output_buffer, field_order)
writer.writeheader()
for page, rows in page_position_data.items():
for text_char_data_row in rows:
writer.writerow(text_char_data_row)
stored_format = zlib.compress(output_buffer)
这会成功地将每一行读入 io.StringIO 缓冲区,但是 gzip/zlib 似乎只适用于类似字节的对象,例如 io.BytesIO 所以最后一行错误;我无法创建将 csv 读入 BytesIO 缓冲区,因为 DictWriter/Writer 错误,除非使用 io.StringIO()。
感谢您的帮助!
我想通了,想向遇到此问题的任何人展示我的答案:
问题是 zlib.compress 需要一个类似字节的对象;这实际上并不意味着 StringIO 或 BytesIO,因为它们都是 "file-like" 实现 read() 和普通 unix 文件句柄的对象。
要解决此问题,您只需使用 StringIO() 写入 csv 文件,然后调用从 StringIO() 对象中获取字符串并将其编码为字节串;然后它可以被 zlib 压缩。
import io
import csv
import zlib
# This data file is sent over Flask
page_position_data = pdf_parse_page_layouts(data_file)
field_order = ['char', 'position', 'page']
output_buffer = io.StringIO()
writer = csv.DictWriter(output_buffer, field_order)
writer.writeheader()
for page, rows in page_position_data.items():
for text_char_data_row in rows:
writer.writerow(text_char_data_row)
encoded = output_buffer.getvalue().encode()
stored_format = zlib.compress(encoded)
对于任何感兴趣的人,我有一个替代答案,应该使用较少的中间 space,它需要 python 3.3 及以上才能使用 getbuffer()
方法:
from io import BytesIO, TextIOWrapper
import csv
import zlib
def compress_csv(series):
byte_buf = BytesIO()
fp = TextIOWrapper(byte_buf, newline='', encoding='utf-8')
writer = csv.writer(fp)
for row in series:
writer.writerow(row)
compressed = zlib.compress(byte_buf.getbuffer())
fp.close()
byte_buf.close()
return compressed