Python 3,从/向gzip文件

时间:2016-09-12 12:13:44

标签: json python-3.x gzip

对于Python3,我跟着@Martijn Pieters's code跟着:

import gzip
import json

# writing
with gzip.GzipFile(jsonfilename, 'w') as fout:
    for i in range(N):
        uid = "whatever%i" % i
        dv = [1, 2, 3]
        data = json.dumps({
            'what': uid,
            'where': dv})

        fout.write(data + '\n')

但这会导致错误:

Traceback (most recent call last):
    ...
  File "C:\Users\Think\my_json.py", line 118, in write_json
    fout.write(data + '\n')
  File "C:\Users\Think\Anaconda3\lib\gzip.py", line 258, in write
    data = memoryview(data)
TypeError: memoryview: a bytes-like object is required, not 'str'

有关正在发生的事情的任何想法?

2 个答案:

答案 0 :(得分:55)

这里有四个转换步骤。

  1. Python数据结构(嵌套的dicts,列表,字符串,数字,布尔值)
  2. 包含该数据结构的序列化表示形式的Python字符串(“JSON”)
  3. 包含该字符串表示的字节列表(“UTF-8”)
  4. 包含该前一个字节列表(“gzip”)
  5. 表示的字节列表

    让我们逐一采取这些步骤。

    import gzip
    import json
    
    data = []
    for i in range(N):
        uid = "whatever%i" % i
        dv = [1, 2, 3]
        data.append({
            'what': uid,
            'where': dv
        })                                           # 1. data
    
    json_str = json.dumps(data) + "\n"               # 2. string (i.e. JSON)
    json_bytes = json_str.encode('utf-8')            # 3. bytes (i.e. UTF-8)
    
    with gzip.GzipFile(jsonfilename, 'w') as fout:   # 4. gzip
        fout.write(json_bytes)                       
    

    请注意,添加"\n"在这里完全是多余的。它没有破坏任何东西,但除此之外没有任何用处。

    阅读完全相反:

    with gzip.GzipFile(jsonfilename, 'r') as fin:    # 4. gzip
        json_bytes = fin.read()                      # 3. bytes (i.e. UTF-8)
    
    json_str = json_bytes.decode('utf-8')            # 2. string (i.e. JSON)
    data = json.loads(json_str)                      # 1. data
    
    print(data)
    

    当然可以合并步骤:

    with gzip.GzipFile(jsonfilename, 'w') as fout:
        fout.write(json.dumps(data).encode('utf-8'))                       
    

    with gzip.GzipFile(jsonfilename, 'r') as fin:
        data = json.loads(fin.read().decode('utf-8'))
    

答案 1 :(得分:2)

https://stackoverflow.com/a/49535758/1236083中提到的解决方案(感谢@Rafe)具有很大的优势:由于编码是即时进行的,因此您不会为生成的json创建两个完整的中间字符串对象。对于大物体,这可以节省内存。

除了提到的帖子,解码也很简单:

with gzip.open(filename, 'rt', encoding='ascii') as zipfile:
    my_object = json.load(zipfile)