Как мне записать данные JSON в файл?

834

У меня есть данные JSON, хранящиеся в переменной data.

Я хочу записать это в текстовый файл для тестирования, поэтому мне не нужно каждый раз захватывать данные с сервера.

В настоящее время я пытаюсь это сделать:

obj = open('data.txt', 'wb')
obj.write(data)
obj.close

И я получаю ошибку:

TypeError: must be string or buffer, not dict

Как это исправить?

Теги:

14 ответов

1580
Лучший ответ

Вы забыли фактическую часть JSON - data являются словарем и еще не закодированы в JSON. Напишите это так:

import json
with open('data.json', 'w') as outfile:
    json.dump(data, outfile)

Примечание: работает на 3.x и 2.x.

  • 6
    это может быть полезно для сериализации: stackoverflow.com/questions/4512982/…
  • 8
    Вы имеете в виду json.dump или json.dumps?
Показать ещё 18 комментариев
221

Чтобы получить файл utf8 -encoded в отличие от ascii -encoded в принятом ответе для Python 2, используйте:

import io, json
with io.open('data.txt', 'w', encoding='utf-8') as f:
  f.write(json.dumps(data, ensure_ascii=False))

Код проще в Python 3:

import json
with open('data.txt', 'w') as f:
  json.dump(data, f, ensure_ascii=False)

В Windows аргумент encoding='utf-8' для open по-прежнему необходим.

Чтобы не хранить зашифрованную копию данных в памяти (результат создания dumps) и выводить строки байтов utf8 -encoded в Python 2 и 3, используйте:

import json, codecs
with open('data.txt', 'wb') as f:
    json.dump(data, codecs.getwriter('utf-8')(f), ensure_ascii=False)

codecs.getwriter является избыточным в Python 3, но требуется для Python 2


Читаемость и размер:

Использование ensure_ascii=False обеспечивает лучшую читаемость и меньший размер:

>>> json.dumps({'price': '€10'})
'{"price": "\\u20ac10"}'
>>> json.dumps({'price': '€10'}, ensure_ascii=False)
'{"price": "€10"}'

>>> len(json.dumps({'абвгд': 1}))
37
>>> len(json.dumps({'абвгд': 1}, ensure_ascii=False).encode('utf8'))
17

Дальнейшее улучшение читабельности путем добавления флагов indent=4, sort_keys=True (как предложено dinos66) к аргументам dump или dumps. Таким образом, вы получите аккуратно отсортированную структуру с отступом в файле json за счет немного большего размера файла.

  • 5
    unicode json.dumps - результат json.dumps уже является объектом юникода. Обратите внимание, что это не работает в 3.x, где весь этот беспорядок режима выходного файла был очищен, и json всегда использует символьные строки (и символьный ввод / вывод) и никогда не байты.
  • 4
    В 2.x type(json.dumps('a')) равен <type 'str'> . Четный type(json.dumps('a', encoding='utf8')) - это <type 'str'> .
Показать ещё 16 комментариев
157

Я бы ответил небольшими изменениями с вышеупомянутыми ответами, а именно, чтобы написать префиксный файл JSON, который человеческие глаза могут читать лучше. Для этого пройдите sort_keys как True и indent с 4 пробелами, и вам хорошо идти. Также следите за тем, чтобы коды ascii не записывались в ваш JSON файл:

with open('data.txt', 'w') as outfile:
     json.dump(jsonData, outfile, sort_keys = True, indent = 4,
               ensure_ascii = False)
  • 2
    все еще получает UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc'
  • 1
    @SirBenBenji Убедитесь, что строка, которую вы пытаетесь написать, должна следовать: str.decode ('utf-8').
Показать ещё 3 комментария
92

Чтение и запись файлов JSON с помощью Python 2 + 3; работает с юникодом

# -*- coding: utf-8 -*-
import json

# Make it work for Python 2+3 and with Unicode
import io
try:
    to_unicode = unicode
except NameError:
    to_unicode = str

# Define data
data = {'a list': [1, 42, 3.141, 1337, 'help', u'€'],
        'a string': 'bla',
        'another dict': {'foo': 'bar',
                         'key': 'value',
                         'the answer': 42}}

# Write JSON file
with io.open('data.json', 'w', encoding='utf8') as outfile:
    str_ = json.dumps(data,
                      indent=4, sort_keys=True,
                      separators=(',', ': '), ensure_ascii=False)
    outfile.write(to_unicode(str_))

# Read JSON file
with open('data.json') as data_file:
    data_loaded = json.load(data_file)

print(data == data_loaded)

Объяснение параметров json.dump:

  • indent: используйте 4 пробела для отступа каждой записи, например, когда начинается новый dict (иначе все будут в одной строке),
  • sort_keys: сортировать ключи словарей. Это полезно, если вы хотите сравнить файлы json с помощью инструмента сравнения/поставить их под контроль версий.
  • separators: чтобы запретить Python добавлять конечные пробелы

С пакетом

Взгляните на мой пакет mpu для супер простого и легко запоминающегося:

import mpu.io
data = mpu.io.read('example.json')
mpu.io.write('example.json', data)

Создан файл JSON

{
    "a list":[
        1,
        42,
        3.141,
        1337,
        "help",
        "€"
    ],
    "a string":"bla",
    "another dict":{
        "foo":"bar",
        "key":"value",
        "the answer":42
    }
}

Общие окончания файлов

.json

альтернативы

Для вашего приложения может быть важно следующее:

  • Поддержка другими языками программирования
  • Чтение/запись производительности
  • Компактность (размер файла)

Смотрите также: Сравнение форматов сериализации данных

Если вы предпочитаете создавать конфигурационные файлы, вы можете прочитать мою короткую статью Конфигурационные файлы в Python

  • 2
    Обратите внимание, что по force_ascii флаг force_ascii имеет значение True . Вы будете иметь нечитаемые 6- "\u20ac" последовательности "\u20ac" для каждого в вашем файле json (а также любого другого символа, не являющегося ascii).
  • 0
    Почему вы используете open для чтения, а io.open для записи? Можно ли использовать io.open для чтения, а? Если так, какие параметры должны быть переданы?
Показать ещё 1 комментарий
21

Для тех из вас, кто пытается сбросить греческий или другие "экзотические" языки, такие как я, но также испытывает проблемы (ошибки в Unicode) со странными символами, такими как символ мира (\ u262E) или другие, которые часто содержатся в json формирует данные, такие как Twitter, решение может быть следующим (sort_keys, очевидно, необязательно):

import codecs, json
with codecs.open('data.json', 'w', 'utf8') as f:
     f.write(json.dumps(data, sort_keys = True, ensure_ascii=False))
  • 0
    +1 В то время как docs рекомендует встроенную open версию io.open и ассоциированный io.open над codecs.open , в этом случае это также хороший обратно совместимый хак. В python2 codecs.open более «всеяден», чем io.open (он может «съесть» как str, так и unicode, преобразовав при необходимости). Можно сказать, что эта codecs.open компенсирует причуду json.dumps генерирующую различные типы объектов ( str / unicode ), в зависимости от наличия строк ввода Unicode на входе.
10

У меня недостаточно репутации для добавления комментариев, поэтому я просто пишу некоторые из моих находок этого раздражающего TypeError:

В принципе, я считаю ошибку в функции json.dump() только в Python 2 - он не может выгружать данные Python (словарь/список), содержащие символы не ASCII, даже вы открываете файл с параметром encoding = 'utf-8'. (т.е. независимо от того, что вы делаете). Но json.dumps() работает как на Python 2, так и на 3.

Чтобы проиллюстрировать это, выполните ответ phihag: код в его ответе разбивается на Python 2 с исключением TypeError: must be unicode, not str, если data содержит символы, отличные от ASCII. (Python 2.7.6, Debian):

import json
data = {u'\u0430\u0431\u0432\u0433\u0434': 1} #{u'абвгд': 1}
with open('data.txt', 'w') as outfile:
    json.dump(data, outfile)

Однако он отлично работает в Python 3.

  • 0
    Укажите причины, когда вы заявляете, что что-то не так. Используйте @nickname, чтобы человек получал уведомления. Вы не можете писать комментарии, но вы можете читать комментарии. Как уже говорилось в моем ответе на первый комментарий, попробуйте data = {'asdf': 1} . Вы получите пресловутую TypeError с вашим (вторым) вариантом.
  • 0
    По поводу ensure_ascii - это необходимо, если вы хотите получить «настоящий» вывод utf8. Без него у вас будет простой ascii с 6 байтами на русскую букву, а не 2 байта на символ с этим флагом.
Показать ещё 2 комментария
7

Запишите данные в файл, используя JSON, используйте json.dump() или json.dumps(). напишите так, чтобы сохранить данные в файле.

import json
data = [1,2,3,4,5]
with open('no.txt', 'w') as txtfile:
    json.dump(data, txtfile)

этот пример в списке хранится в файле.

  • 0
    Чем он отличается от принятого ответа?
  • 0
    это похоже, но привести пример
4
json.dump(data, open('data.txt', 'wb'))
  • 2
    Это делает то же самое, что и ответ @ phihag, но не всегда работает. Рассмотрим такой код: f = open('1.txt', 'w'); f.write('a'); input() . Запустите его и затем выполните SYGTERM ( Ctrl-Z затем kill %1 в Linux, Ctrl-Break в Windows). 1.txt будет иметь 0 байтов. Это связано с тем, что запись была буферизована, а файл не был ни сброшен, ни закрыт в момент возникновения SYGTERM. with блоком гарантирует, что файл всегда будет закрыт так же, как блок «try / finally», но короче.
2

Чтобы написать JSON с отступом "pretty print":

import json

outfile = open('data.json')
json.dump(data, outfile, indent=4)

Кроме того, если вам нужно отладить неправильно отформатированный JSON и получить полезное сообщение об ошибке, используйте библиотеку import simplejson вместо import json (функции должны быть такими же)

2

если вы пытаетесь записать фреймворк pandas в файл, используя формат json, я бы рекомендовал этот

destination='filepath'
saveFile = open(destination, 'w')
saveFile.write(df.to_json())
saveFile.close()
0

Данные JSON могут быть записаны в файл следующим образом

hist1 = [{'val_loss': [0.5139984398465246],
'val_acc': [0.8002029867684085],
'loss': [0.593220705309384],
'acc': [0.7687131817929321]},
{'val_loss': [0.46456472964199463],
'val_acc': [0.8173602046780344],
'loss': [0.4932038113037539],
'acc': [0.8063946213802453]}]

Написать в файл:

with open('text1.json', 'w') as f:
     json.dump(hist1, f)
0

Принятый ответ в порядке. Тем не менее, я столкнулся с ошибкой "не json serializable", используя это.

Вот как я исправил это с помощью open("file-name.json", 'w') качестве вывода:

output.write(str(response))

Хотя это не очень удачное решение, так как создаваемый файл json не будет содержать двойных кавычек, однако будет неплохо, если вы ищете быстрый и грязный файл.

0

Все предыдущие ответы верны, вот очень простой пример:

#! /usr/bin/env python
import json

def write_json():
    # create a dictionary  
    student_data = {"students":[]}
    #create a list
    data_holder = student_data["students"]
    # just a counter
    counter = 0
    #loop through if you have multiple items..         
    while counter < 3:
        data_holder.append({'id':counter})
        data_holder.append({'room':counter})
        counter += 1    
    #write the file        
    file_path='/tmp/student_data.json'
    with open(file_path, 'w') as outfile:
        print("writing file to: ",file_path)
        # HERE IS WHERE THE MAGIC HAPPENS 
        json.dump(student_data, outfile)
    outfile.close()     
    print("done")

write_json()

Изображение 2510

0

Вот полезная структура для чтения и записи файла в Python 3.

from json import dump, load
from time import sleep
from random import random

def json_file(path, data = None, delay = 0.1):
    while True:
        try:
            if data == None:
                with open(path, "r", encoding = "utf-8") as f:
                    return load(f)
            else:
                with open(path, "w", encoding = "utf-8") as f:
                    return dump(data, f)
        except:
            sleep(random()*delay) # concurrency

Ещё вопросы

Сообщество Overcoder
Наверх
Меню