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

avatar
user1530318
6 сентября 2012 в 22:21
1834065
15
1383

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

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

В настоящее время я пробую это:

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

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

TypeError: должна быть строка или буфер, а не dict

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

Источник
Charlie Parker
22 сентября 2020 в 17:14
0

Для флагов при открытии файла: здесь мы использовали букву «w» в нашем аргументе, которая указывает на запись и создаст файл, если он не существует в библиотеке. Знак «плюс» указывает и на чтение, и на запись, guru99.com/reading- and-writing-files-in-python.html # 1

Ответы (15)

avatar
phihag
6 сентября 2012 в 22:23
2484

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

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

В современной системе (например, с поддержкой Python 3 и UTF-8) вы можете написать более удобный файл с помощью

import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)
jedierikb
11 февраля 2013 в 17:27
9

это может быть полезно для сериализации: coderhelper.com/questions/4512982/…

TerminalDilettante
13 августа 2015 в 14:46
13

Вы имеете в виду json.dump или json.dumps?

phihag
13 августа 2015 в 20:58
196

@TerminalDilettante json.dump записывает в файл или файловый объект, тогда как json.dumps возвращает строку.

klaas
7 марта 2016 в 12:59
34

кстати: для повторного чтения данных используйте: с open ('data.txt') как infile: d = json.load (infile). См .: этот ответ

jesperk.eth
19 апреля 2016 в 18:40
0

Должно ли это быть «wb» вместо «w» (скорость и т. Д.)?

phihag
19 апреля 2016 в 18:47
9

@denvar Нет, этот ответ точно настроен. В Python 3 json.dump записывает в текстовый файл, а не в двоичный файл. Вы получите TypeError, если бы файл был открыт с wb. В более старых версиях Python работают как w, так и wb. Явное кодирование не требуется, поскольку вывод json.dump по умолчанию является только ASCII. Если вы можете быть уверены, что ваш код никогда не запускается в устаревших версиях Python, и вы и обработчик файла JSON можете правильно обрабатывать данные, отличные от ASCII, вы можете указать один и установить ensure_ascii=False.

phihag
13 декабря 2016 в 20:18
1

@marctrem Не могли бы вы объяснить, почему вы так думаете? Вопрос касается записи в файл с именем data.txt. В любом случае имя файла значения не имеет.

Antony Hatchkins
10 февраля 2017 в 10:05
0

Да, это работает. Но это решение дает 7-битный вывод как для python2, так и для python3: все символы, отличные от ascii, кодируются как ascii (например, 'π' кодируется как 6 байтов: '\u03c0'). Сегодня неплохо иметь файлы json в кодировке utf8. Они в 3 раза меньше ('π' кодируется всего двумя байтами: b'\xcf\x80'), плюс они читаются в любом современном редакторе (читаемость является одним из основных преимуществ json по сравнению с xml). Подробности см. В моем ответе ниже.

user305883
15 февраля 2017 в 15:14
0

Я попал в `` File "/Users/gg4u/Sites/expo_recipes_2015/scraper.py", line 282, in downloadRecipe json.dump({'data' : 'data'}, out_file) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py", line 180, in dump fp.write(chunk) TypeError: a bytes-like object is required, not 'str' '' в Python 3

kRazzy R
24 октября 2017 в 20:05
0

где сохраняется получившийся файл data.txt? как мне получить к нему доступ в ubuntu 16.04?

phihag
24 октября 2017 в 20:26
1

@kRazzyR Вместо data.txt вы можете передать любой путь из любого места, где вы хотите файл. Например, если ваше имя пользователя krazzyr в Ubuntu, вы можете передать '/home/krazzyr/Desktop/myfile.json', и файл появится на вашем рабочем столе. Если путь не начинается с косой черты (/), он относится к вашему текущему рабочему каталогу. Например, если ваш рабочий каталог /home/krazzyr и вы передаете data.txt, имя файла будет /home/krazzyr/data.txt. В оболочке вы можете ввести pwd, чтобы распечатать рабочий каталог.

phihag
24 октября 2017 в 20:30
1

@kRazzyR Как вы получите к нему доступ, зависит от того, что вы хотите сделать. Популярные варианты включают текстовые редакторы командной строки, такие как nano или vi, графические текстовые редакторы, такие как emacs, kwrite, gedit или sublime text, редакторы IDE, такие как vscode и Eclipse, вывод командной строки с cat или less и цветной или отфильтрованный дисплей с jq. Как правило, в командной строке введите программу, которую вы хотите запустить, а затем путь. Опять же, пути могут быть относительными или абсолютными. Например, если вы сохранили свой файл в /home/krazzyr/Desktop/myfile.json, а ваш рабочий каталог - /home/krazzyr, подойдет gedit Desktop/myfile.json.

kRazzy R
24 октября 2017 в 23:21
0

Спасибо за такое полезное и подробное объяснение. (Я в первую очередь пользователь R, перешедший на Python.) Поэтому изменение open('data.txt', 'w') на open('/home/krazzyr/data.txt', 'w') приведет к созданию файла data.txt и сохранению файла в home/krazzyr/.

phihag
25 октября 2017 в 06:08
0

@kRazzyR Почти: абсолютные пути начинаются с косой черты, поэтому файл заканчивается в /home/krazzyr - обратите внимание на начальную косую черту. Но не бойтесь относительных путей, они часто более полезны. Если вы просто укажете data.txt и запустите программу, находясь в /home/krazzyr (по умолчанию), ваш файл также окажется в /home/krazzyr/. Но когда я запускаю вашу программу в /home/phihag/coderhelper/, она записывает ее в /home/phihag/coderhelper/. Это полезно, потому что /home/krazzyr/ может не существовать в моей системе, и мне все равно нужен вывод программы в подкаталоге.

kRazzy R
3 ноября 2017 в 15:31
0

В моей программе есть метод, который выполняется трижды. Поэтому вместо w я поставил a. Теперь, как мне добавить новую строку или что-то подобное в выходной файл после каждого запуска, чтобы я мог различать все три разных вывода в файле, сгенерированном из этого: import json with open('data.txt', 'a') as outfile: json.dump(data, outfile)

phihag
3 ноября 2017 в 22:45
0

@kRazzyR Звучит как отличный вопрос. Давайте, спросите на coderhelper!

Mnebuerquo
8 января 2018 в 15:47
0

@kRazzyR, если вы задаете это как вопрос, разместите ссылку на него в комментарии здесь. Думаю, это достаточно связано.

kRazzy R
8 января 2018 в 16:36
0

Да, это так. но к тому времени, как я нашел решение, мой вопрос был помечен как повторяющийся. вот он: coderhelper.com/questions/47140526/…

phihag
31 декабря 2018 в 07:58
0

@Gulzar Это другой вопрос. (Спойлер: используйте json.load)

NoobCat
18 сентября 2020 в 15:40
0

Второй способ работает на всех последних системах Windows, Macintosh, linux?

phihag
19 сентября 2020 в 18:11
1

@Pastrokkio Да, при условии, что вы хотите записать файл как UTF-8, и у вас есть Python 3.

Charlie Parker
22 сентября 2020 в 17:11
0

какой флаг использовать w, `w + ',' a + '? Я хочу создать файл, если он не существует, и каждый раз писать в него с нуля.

Charlie Parker
22 сентября 2020 в 17:13
0

# Здесь мы использовали букву "w" в нашем аргументе, которая указывает на запись и создаст файл, если он не существует в библиотеке # Знак плюс указывает и на чтение, и на запись.

phihag
22 сентября 2020 в 21:24
1

@CharlieParker Тогда w правильный. w+ очень редко бывает правильным; + означает, что вы хотите позже прочитать из того же файлового указателя.

phihag
11 февраля 2021 в 20:14
1

@CharlieParker Да, json.dump(data, open(path, 'w')) будет однострочным. Однако опускание оператора with может привести к проблемам в долго выполняющихся программах. В десятистрочном сценарии вреда нет, но если вы пишете код, который можно использовать как библиотеку или долго работающее приложение, вы должны использовать with.

Charlie Parker
11 февраля 2021 в 22:58
0

@phihag, дай мне посмотреть, понимаю ли я. Так что это проблема, потому что, если я сделаю один лайнер, мне все равно придется закрыть файл (но у меня даже нет дескриптора для него, поэтому я не могу его закрыть, поэтому он может быть поврежден ... по какой-то мистической причине ?)

phihag
12 февраля 2021 в 00:00
1

@CharlieParker Дескриптор не становится поврежденным , но может оставаться в памяти. В замкнутом цикле это может вызвать истощение ручки. Нет никакой гарантии, когда и будет ли Python собирать (а затем автоматически закрывать) устаревшие дескрипторы. Кроме того, если вы не вызывали close (вручную или в операторе with), то нет гарантии, что файл был очищен и последние байты могут отсутствовать. Если файл находится в сетевой файловой системе и не все байты были переданы, то строка после json.dump может заставить другую программу прочитать файл и найти неполный файл.

avatar
questionto42
13 сентября 2021 в 12:16
-2

Это просто дополнительный намек на использование json.dumps (это не ответ на проблему вопроса, а уловка для тех, кому нужно сбрасывать несколько типов данных):

Если в словаре есть типы данных NumPy, json.dumps() требуется дополнительный параметр, кредиты переходят к TypeError: объект типа 'ndarray' не сериализуемый JSON , и он также исправит такие ошибки, как TypeError: Object of type int64 is not JSON serializable и так далее:

class NumpyEncoder(json.JSONEncoder):
    """ Special json encoder for np types """
    def default(self, obj):
        if isinstance(obj, (np.int_, np.intc, np.intp, np.int8,
                            np.int16, np.int32, np.int64, np.uint8,
                            np.uint16, np.uint32, np.uint64)):
            return int(obj)
        elif isinstance(obj, (np.float_, np.float16, np.float32,
                              np.float64)):
            return float(obj)
        elif isinstance(obj, (np.ndarray,)):
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)

А затем запустите:

import json

#print(json.dumps(my_data[:2], indent=4, cls=NumpyEncoder)))
with open(my_dir+'/my_filename.json', 'w') as f:
    json.dumps(my_data, indent=4, cls=NumpyEncoder)))

Вы также можете захотеть вернуть строку вместо списка в случае np.array (), поскольку массивы печатаются как списки, распределенные по строкам, что приведет к увеличению вывода, если у вас большой или много массивов. Предостережение: позже будет труднее получить доступ к элементам из сброшенного словаря, чтобы вернуть их как исходный массив. Тем не менее, если вы не против иметь только строку массива, это сделает словарь более читабельным. Затем обменяйте:

        elif isinstance(obj, (np.ndarray,)):
            return obj.tolist()

с:

        elif isinstance(obj, (np.ndarray,)):
            return str(obj)

или просто:

        else:
            return str(obj)
user32882
2 ноября 2021 в 09:17
0

Какой окольный способ сделать что-то действительно простое

questionto42
2 ноября 2021 в 10:09
0

@ user32882 Да, меня это тоже поразило. Такое слабое место такого стандарта, как json.dumps. Возможно, за него проголосовали против, потому что никто не ожидал, что он будет настолько сложным (включая меня), и на самом деле он не отвечает на вопрос, но в моем случае мне это было нужно.

questionto42
2 ноября 2021 в 12:20
0

@ user32882 Теперь я вижу, что вы проголосовали против этого комментария? Ваш комментарий скорее поддержит этот ответ, поскольку нет простого способа сделать это вместо этого, а именно критиковать json.dumps, но не этот ответ. У вас есть лучший способ сделать это?

user32882
2 ноября 2021 в 13:19
0

пожалуйста, взгляните на принятый ответ. Это не должно занять больше пары строк кода.

questionto42
2 ноября 2021 в 14:19
0

@ user32882 Насколько я помню, принятый ответ не может экспортировать типы данных numpy, поэтому я добавил этот ответ. Однако я не уверен, есть ли разница в типах данных numpy между json.dump и json.dumps, я не могу найти время, чтобы проверить это сейчас, и я думаю, что все равно это тестировал. Этот ответ не заменяет принятый ответ, но добавляет этот особый случай (совсем не особенный, часто встречаются типы данных numpy).

questionto42
3 ноября 2021 в 14:01
0

@ user32882 Читая ваши комментарии, вы не поняли этот ответ. Принятый ответ более или менее повторяется здесь (dumps вместо dump здесь, чтобы вы могли использовать параметры), и просто добавляется класс, который делает возможным экспорт numpy. Ничего не имею против голосования против, но, пожалуйста, подумайте над этим.

avatar
iman
26 декабря 2019 в 08:35
17

Запись JSON в файл

import json

data = {}
data['people'] = []
data['people'].append({
    'name': 'Scott',
    'website': 'stackabuse.com',
    'from': 'Nebraska'
})
data['people'].append({
    'name': 'Larry',
    'website': 'google.com',
    'from': 'Michigan'
})
data['people'].append({
    'name': 'Tim',
    'website': 'apple.com',
    'from': 'Alabama'
})

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

Чтение JSON из файла

import json

with open('data.txt') as json_file:
    data = json.load(json_file)
    for p in data['people']:
        print('Name: ' + p['name'])
        print('Website: ' + p['website'])
        print('From: ' + p['from'])
        print('')
Jonathan Leffler
26 декабря 2019 в 09:05
3

Добро пожаловать в Stack Overflow. Если вы решите ответить на старый вопрос, на который есть хорошо обоснованные и правильные ответы, добавление нового ответа в конце дня может не принести вам никакого кредита. Если у вас есть какая-то особенная новая информация или вы убеждены, что все остальные ответы неверны, обязательно добавьте новый ответ, но «еще один ответ», дающий ту же основную информацию через долгое время после того, как вопрос был задан, обычно выигрывал » Я не заслуживаю большого уважения. (Вы показываете некоторые образцы данных; это хорошо, но я не уверен, что этого достаточно, особенно потому, что вы не показываете, что создается для образцов данных.)

M.Innat
2 декабря 2020 в 07:54
1

Я думаю, что ответ нормальный, потому что он содержит больше деталей и ясности.

avatar
James Wierzba
13 декабря 2018 в 22:38
5

Чтобы записать JSON с отступом, "красивый шрифт":

import json

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

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

Mihai Todor
25 апреля 2021 в 22:57
0

Разве open('data.json') не открывает файл в режиме только для чтения?

avatar
Ashok Kumar Jayaraman
1 ноября 2018 в 12:00
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)
avatar
Akshat Bajaj
15 октября 2018 в 04:10
1

Ответ принят. Однако при этом я столкнулся с ошибкой "не json serializable".

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

output.write(str(response))

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

avatar
grepit
10 октября 2018 в 05:36
3

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

#! /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()

enter image description here

avatar
Franco Miguel Contreras
3 июня 2017 в 07:48
2

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

destination='filepath'
saveFile = open(destination, 'w')
saveFile.write(df.to_json())
saveFile.close()
avatar
Martin Thoma
13 июня 2016 в 16:43
123

Чтение и запись файлов 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

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

  • CSV: сверхпростой формат (чтение и запись)
  • JSON: удобен для записи удобочитаемых данных; ОЧЕНЬ часто используется (чтение и запись)
  • YAML: YAML - это надмножество JSON, но его легче читать (чтение и запись, сравнение JSON и YAML)
  • pickle: формат сериализации Python (чтение и запись)
  • MessagePack (пакет Python): более компактное представление (чтение и запись)
  • HDF5 (пакет Python): хорошо для матриц (чтение и запись)
  • XML: тоже существует * вздох * (чтение и запись)

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

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

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

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

Antony Hatchkins
10 февраля 2017 в 11:13
2

Обратите внимание, что флаг force_ascii по умолчанию равен True. У вас будут нечитаемые 6-байтовые последовательности "\u20ac" для каждого в вашем файле json (а также любого другого символа, отличного от ascii).

Micah Zoltu
5 июня 2017 в 05:31
0

Почему вы используете open для чтения, а io.open для записи? Возможно ли использовать io.open для чтения? Если да, то какие параметры следует передать?

avatar
Alexander
29 февраля 2016 в 20:16
5
json.dump(data, open('data.txt', 'wb'))
Antony Hatchkins
10 февраля 2017 в 10:27
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, но короче.

avatar
ibic
3 января 2016 в 06:52
11

У меня недостаточно репутации, чтобы добавлять в комментарии, поэтому я просто пишу некоторые из своих выводов об этой надоедливой 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.

Antony Hatchkins
10 февраля 2017 в 08:55
0

Объясните причины, когда вы утверждаете, что что-то не так. Используйте @nickname, чтобы человек получил уведомление. Вы не можете писать комментарии, но можете читать комментарии. Как уже было сказано в моем ответе на первый комментарий, попробуйте data = {'asdf': 1}. Вы получите пресловутый TypeError с вашим (вторым) вариантом.

Antony Hatchkins
10 февраля 2017 в 08:56
0

По поводу ensure_ascii - это необходимо, если вы хотите получить "настоящий" вывод utf8. Без него у вас будет простой ascii с 6 байтами на русскую букву, в отличие от 2 байтов на символ с этим флагом.

ibic
12 февраля 2017 в 16:29
0

@AntonyHatchkins. Вы правы в части unicode(). Я только что понял, что для пакета io в Python 2 write() нужен unicode, а не str.

Antony Hatchkins
21 февраля 2017 в 04:40
1

Этот код у меня работает даже с python2.6.6, Debian (10 декабря 2010 г.). Как и с python2.7.9 или python3. Проверьте еще раз, плз.

avatar
Vishal Gediya
24 декабря 2015 в 10:58
10

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

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

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

Vishal Gediya
17 февраля 2017 в 07:30
0

это похоже, но приведите пример

avatar
dinos66
10 июля 2015 в 14:45
25

Для тех из вас, кто пытается избавиться от греческого или других «экзотических» языков, таких как я, но также испытывает проблемы (ошибки 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))
Antony Hatchkins
10 февраля 2017 в 11:06
1

+1 Хотя документы рекомендуют встроенный python3 open и связанный io.open вместо codecs.open, в этом случае это также хороший способ обратной совместимости. В python2 codecs.open более «всеяден», чем io.open (он может «съесть» как str, так и unicode, при необходимости конвертируя). Можно сказать, что эта причуда codecs.open компенсирует причуду json.dumps создания различных типов объектов (str / unicode) в зависимости от наличия строк Unicode во входных данных.

avatar
ambodi
25 декабря 2013 в 20:04
170

Я бы ответил с небольшими изменениями вышеупомянутыми ответами, а именно, чтобы написать предварительно настроенный файл 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)
Steve K
13 октября 2014 в 23:16
2

все еще получаю UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc'

ambodi
22 апреля 2015 в 09:08
1

@SirBenBenji Убедитесь, что строка, которую вы пытаетесь написать, должна следовать: str.decode ('utf-8').

Shiv
3 сентября 2015 в 19:01
1

@SirBenBenji Вы также можете попробовать использовать кодеки, как указывает dinos66 ниже

aesede
2 апреля 2016 в 17:29
0

Вы также должны объявить свою кодировку, добавив # -*- coding: utf-8 -*- после shebang

Antony Hatchkins
10 февраля 2017 в 10:41
2

+1 для sort_keys и отступа. @aesede Нехорошо добавлять эту строку, потому что это создаст впечатление, что это решение также работает с python2, чего не делает (UnicodeEncodeError с данными, отличными от ascii). Подробности см. В моем решении.

avatar
Antony Hatchkins
14 февраля 2013 в 08:22
281

Чтобы получить utf8 -кодированный файл вместо в формате в кодировке Python, используйте кодировку ascii <348832971> принятый код 348629 в кодировке 348832971.28 >

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 как в 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 за счет немного большего размера файла.

phihag
14 февраля 2013 в 11:20
5

unicode является лишним - результат json.dumps уже является объектом Unicode. Обратите внимание, что это не удается в 3.x, где весь этот беспорядок режима выходного файла был очищен, и json всегда использует символьные строки (и символьный ввод-вывод), а не байты.

Antony Hatchkins
14 февраля 2013 в 11:25
4

В 2.x type(json.dumps('a')) это <type 'str'>. Даже type(json.dumps('a', encoding='utf8')) - это <type 'str'>.

Antony Hatchkins
14 февраля 2013 в 11:39
4

Да, в 3.x json использует строки, но по умолчанию используется кодировка ascii. Вы должны явно указать, что хотите utf8 даже в 3.x. Обновил ответ.

dinos66
9 июля 2015 в 13:08
0

Поставщики данных, такие как twitter, иногда предоставляют данные в различной кодировке. Приведенный выше код отлично работает для всех твитов в Юникоде, но в некоторых случаях появляются латинские символы и возникают такие ошибки, как: 'UnicodeEncodeError: кодек' charmap 'не может кодировать символ' \ xdc 'в позиции 3088: символы сопоставляются с <undefined> 'Есть идеи, что можно сделать в этих случаях?

Antony Hatchkins
10 июля 2015 в 04:47
0

@ dinos66 Можно ли вывести строку на консоль Unicode без этой ошибки? Попробуйте локализовать проблему, найдите как минимум 5-7 байтов до и после проблемного символа и укажите их здесь. Моя версия, что раньше строка была некорректно декодирована в юникод.

dinos66
10 июля 2015 в 14:37
0

@AntonyHatchkins Спасибо за проявленный интерес. Мне удалось решить эту проблему с помощью библиотеки кодеков lib. Итак, мое решение было бы: с codecs.open ('data.txt', 'w', 'utf8') как outfile: outfile.write (json.dumps (jsonData, sort_keys = True, sure_ascii = False))

Blairg23
22 декабря 2015 в 18:44
1

Ответ Python 3.x сработал для меня, хотя я использую 2.7. Ответ 2.x вернул ошибку: 'ascii' codec can't decode byte 0xf1 in position 506755: ordinal not in range(128). Поэтому, если сомневаетесь, используйте ответ 3.x!

Antony Hatchkins
22 декабря 2015 в 19:58
0

@ Blairg23 Это потому, что вы имеете дело с не-ascii str в однобайтовой кодировке. Это настоятельно не рекомендуется. Используйте нотацию u'' для литералов вместо ''. Например, unicode('абвгд') дает ошибку в python2.x: вы должны либо явно указать 'абвгд'.decode('utf8') строку, либо использовать нотацию u'абвгд'.

user305883
15 февраля 2017 в 15:19
0

мне codecs.getwriter был необходим в python 3. В противном случае: json.dump( recipe , ensure_ascii=False) TypeError: dump() missing 1 required positional argument: 'fp'

Antony Hatchkins
16 февраля 2017 в 03:49
0

@ user305883 Это потому, что вы пропустили обязательный позиционный аргумент fp. getwriter не является обязательным, но f необходимо. См. Мое решение для python3.x

Antony Hatchkins
5 марта 2017 в 15:54
0

@Cas Спасибо за редактирование, я исправил в нем пару опечаток, но в целом, написанное таким образом, дает намного лучший опыт чтения :)

Odysseus Ithaca
30 марта 2017 в 21:09
0

Это сработало для меня, когда вышеупомянутый метод вставлял в мой файл контрольный канал '\ n' и обратную косую черту '\'.

mpacer
4 мая 2017 в 00:25
0

Это лучший ответ, чем принятый, поскольку он передает сложность всего, что здесь происходит. Тем не менее, я до сих пор не совсем понимаю, почему решение с использованием явного диспетчера контекста кодирования with io.open('data.txt', 'w', encoding='utf-8') as f: не может работать для подхода json.dump, но, тем не менее, это помогло мне решить мою проблему с codex.getwriter('utf-8')(f) и двоичным доступом. Я предполагаю, что это как-то связано с тем, что ожидает json.dump, но, читая его, я не могу понять, что на самом деле это делает.

rik
29 июня 2017 в 15:02
0

Для Python 3.6.1 мне пришлось добавить аргумент ключевого слова encoding='utf-8' для открытия, чтобы иметь правильную кодировку файла utf-8: import json with open('data.txt', 'w') as f: json.dump(data, f, ensure_ascii=False)

Antony Hatchkins
30 июня 2017 в 10:18
0

@rik Какая у вас ОС?

rik
3 июля 2017 в 15:46
0

@AntonyHatchkins Win 10 x64.

Antony Hatchkins
12 февраля 2021 в 13:25
0

@CharlieParker Как только объект файла выходит за пределы области видимости, CPython автоматически закрывает его. Другие реализации python могут отложить этот шаг, поэтому считается более `` чистым '' заключить его в конструкцию with или явно закрыть файл, чтобы избежать выхода за предел открытых файлов и / или оставить файлы заблокированными для запись (например, вы не можете переместить или удалить их до завершения программы / закрытия записной книжки). На мой взгляд, в CPython безопасно использовать однострочник, но если я напишу это в ответе, то неосведомленные читатели с нетерпением будут отвергать его.

Charlie Parker
12 февраля 2021 в 19:58
0

@AntonyHatchkins Спасибо! CPython? Это отличается от моего обычного питона, который я использую? Мне интересно, есть ли что-нибудь тонкое в вашем ответе мне ...

Antony Hatchkins
15 февраля 2021 в 13:32
0

@CharlieParker CPython = "номинальный питон". Нет, ничего тонкого. Это просто дурная привычка использовать open без with. Например, если вы оставите файл открытым в записной книжке jupyter, у вас возникнут проблемы с переименованием или перемещением этого файла в Windows. Но на самом деле это единственное негативное последствие, о котором я знаю.