【问题标题】:Compress a CSV file written to a StringIO Buffer in Python3在 Python3 中压缩写入 StringIO 缓冲区的 CSV 文件
【发布时间】:2018-08-06 23:48:40
【问题描述】:

我正在将 pdf 文件中的文本解析为有序 char 元数据行;我需要将这些文件序列化到云存储中,这一切都很好,但是由于它们的大小,我也想对这些文件进行 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()。

感谢您的帮助!

【问题讨论】:

    标签: python-3.x csv gzip


    【解决方案1】:

    我想通了这一点,并想向遇到此问题的任何人展示我的答案:

    问题是 zlib.compress 需要一个类似字节的对象;这实际上并不意味着 StringIO 或 BytesIO,因为它们都是实现 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)
    

    【讨论】:

      【解决方案2】:

      对于应该使用较少中间空间的任何感兴趣的人,我有一个替代答案,它需要 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
      

      【讨论】:

        猜你喜欢
        • 2023-03-06
        • 2016-08-02
        • 1970-01-01
        • 2019-08-13
        • 1970-01-01
        • 2023-03-21
        • 1970-01-01
        • 1970-01-01
        • 2011-07-04
        相关资源
        最近更新 更多