У меня есть данные JSON, хранящиеся в переменной data
.
Я хочу записать это в текстовый файл для тестирования, поэтому мне не нужно каждый раз захватывать данные с сервера.
В настоящее время я пытаюсь это сделать:
obj = open('data.txt', 'wb')
obj.write(data)
obj.close
И я получаю ошибку:
TypeError: must be string or buffer, not dict
Как это исправить?
Вы забыли фактическую часть JSON - data
являются словарем и еще не закодированы в JSON. Напишите это так:
import json
with open('data.json', 'w') as outfile:
json.dump(data, outfile)
Примечание: работает на 3.x и 2.x.
Чтобы получить файл 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 за счет немного большего размера файла.
unicode
json.dumps
- результат json.dumps
уже является объектом юникода. Обратите внимание, что это не работает в 3.x, где весь этот беспорядок режима выходного файла был очищен, и json всегда использует символьные строки (и символьный ввод / вывод) и никогда не байты.
type(json.dumps('a'))
равен <type 'str'>
. Четный type(json.dumps('a', encoding='utf8'))
- это <type 'str'>
.
Я бы ответил небольшими изменениями с вышеупомянутыми ответами, а именно, чтобы написать префиксный файл 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)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc'
# -*- 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)
{
"a list":[
1,
42,
3.141,
1337,
"help",
"€"
],
"a string":"bla",
"another dict":{
"foo":"bar",
"key":"value",
"the answer":42
}
}
.json
Для вашего приложения может быть важно следующее:
Смотрите также: Сравнение форматов сериализации данных
Если вы предпочитаете создавать конфигурационные файлы, вы можете прочитать мою короткую статью Конфигурационные файлы в Python
force_ascii
флаг force_ascii
имеет значение True
. Вы будете иметь нечитаемые 6- "\u20ac"
последовательности "\u20ac"
для каждого €
в вашем файле json (а также любого другого символа, не являющегося ascii).
open
для чтения, а io.open
для записи? Можно ли использовать io.open
для чтения, а? Если так, какие параметры должны быть переданы?
Для тех из вас, кто пытается сбросить греческий или другие "экзотические" языки, такие как я, но также испытывает проблемы (ошибки в 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))
open
версию io.open
и ассоциированный io.open
над codecs.open
, в этом случае это также хороший обратно совместимый хак. В python2 codecs.open
более «всеяден», чем io.open (он может «съесть» как str, так и unicode, преобразовав при необходимости). Можно сказать, что эта codecs.open
компенсирует причуду json.dumps
генерирующую различные типы объектов ( str
/ unicode
), в зависимости от наличия строк ввода Unicode на входе.
У меня недостаточно репутации для добавления комментариев, поэтому я просто пишу некоторые из моих находок этого раздражающего 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.
data = {'asdf': 1}
. Вы получите пресловутую TypeError
с вашим (вторым) вариантом.
ensure_ascii
- это необходимо, если вы хотите получить «настоящий» вывод utf8. Без него у вас будет простой ascii с 6 байтами на русскую букву, а не 2 байта на символ с этим флагом.
Запишите данные в файл, используя JSON, используйте json.dump() или json.dumps(). напишите так, чтобы сохранить данные в файле.
import json
data = [1,2,3,4,5]
with open('no.txt', 'w') as txtfile:
json.dump(data, txtfile)
этот пример в списке хранится в файле.
json.dump(data, open('data.txt', 'wb'))
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», но короче.
Чтобы написать JSON с отступом "pretty print":
import json
outfile = open('data.json')
json.dump(data, outfile, indent=4)
Кроме того, если вам нужно отладить неправильно отформатированный JSON и получить полезное сообщение об ошибке, используйте библиотеку import simplejson
вместо import json
(функции должны быть такими же)
если вы пытаетесь записать фреймворк pandas в файл, используя формат json, я бы рекомендовал этот
destination='filepath'
saveFile = open(destination, 'w')
saveFile.write(df.to_json())
saveFile.close()
Данные 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)
Принятый ответ в порядке. Тем не менее, я столкнулся с ошибкой "не json serializable", используя это.
Вот как я исправил это с помощью open("file-name.json", 'w')
качестве вывода:
output.write(str(response))
Хотя это не очень удачное решение, так как создаваемый файл json не будет содержать двойных кавычек, однако будет неплохо, если вы ищете быстрый и грязный файл.
Все предыдущие ответы верны, вот очень простой пример:
#! /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()
Вот полезная структура для чтения и записи файла в 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