2016-09-12 3 views
5

Для Python3, я последовал @Martijn Pieters's code с этим:Python 3, чтение/запись сжатых объектов JSON из/GZIP файла

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' 

Любые мысли о что происходит?

+0

Код был, вероятно, написан с python2 в виду , Попробуйте закодировать данные: '(data + '\ n'). Encode ('utf-8')'. – Bakuriu

+0

@Bakuriu Nope, такой же погрешность. –

ответ

17

У вас есть четыре шага трансформации здесь.

  1. структура данных Python (вложенные dicts, списки, строки, числа, булевы)
  2. Питона строка, содержащая упорядоченное представление этой структуры данных («JSON»)
  3. список байтов, содержащих представление этой строки («UTF-8»)
  4. список байтов, содержащих представление этого списка предыдущего байта («GZIP»)

Итак, давайте эти шаги один за другим.

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')) 
+0

Какой потрясающий и вдумчивый ответ. Он работает сейчас. Благодаря! –

+0

Великолепный и вдумчивый ответ, но, по-видимому, не достоин высоты. Я не понимаю - почему бы вам не нажать «что было полезно» на ответ, который был вам полезен? Я вижу это много, и я не могу не удивляться причинам. – Tomalak

+0

Ooops. Сожалею. Upvoted! Я предполагаю, что большинство людей (включая меня) считают, что, принимая ответ, вы получаете автоматическое повышение. SO, вероятно, должно быть настроено таким образом. пс. Не принимайте это лично. –

Смежные вопросы