Як записати дані JSON у файл?


1121

У мене зберігаються дані JSON у змінній data.

Я хочу записати це в текстовий файл для тестування, щоб мені не потрібно кожного разу захоплювати дані з сервера.

В даний час я намагаюся це:

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

І я отримую цю помилку:

TypeError: повинен бути рядком або буфером, а не диктатом

Як це виправити?

Відповіді:


2039

Ви забули фактичну частину 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)

8
це може бути корисно для сериализации: stackoverflow.com/questions/4512982 / ...
jedierikb

12
Ви маєте на увазі json.dump або json.dumps?
TerminalDilettante

153
@TerminalDilettante json.dumpзаписує у файл або схожий на файл об'єкт, тоді як json.dumpsповертає рядок.
Фігаг

24
btw: для повторного читання використання даних: з відкритим ('data.txt') як infile: d = json.load (infile). Дивіться: ця відповідь
klaas

9
@denvar Ні, ця відповідь тонко налаштована. На Python 3 json.dumpпише текстовий файл, а не бінарний файл. Ви отримаєте, TypeErrorякщо файл було відкрито wb. У старих версіях Python обидва wnand wbпрацюють. Явне кодування не є необхідним, оскільки вихід json.dumpза замовчуванням є лише ASCII. Якщо ви можете бути впевнені, що ваш код ніколи не виконується в застарілих версіях Python, і ви та обробник файлу JSON можете правильно обробляти дані, що не належать до ASCII, ви можете вказати їх і встановити ensure_ascii=False.
Фігаг

267

Щоб отримати 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, в обох 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вже об'єкт Unicode. Зауважте, що це виходить з ладу в 3.x, де весь цей безлад режиму вихідного файлу був очищений, і json завжди використовує символьні рядки (і символьні введення / виведення) і ніколи не байти.
фігаг

4
У 2.х type(json.dumps('a'))є <type 'str'>. Навіть type(json.dumps('a', encoding='utf8'))є <type 'str'>.
Ентоні Хеткінс

4
Так, у 3.x json використовується рядки, проте кодування за замовчуванням - ascii. Ви мусите чітко сказати, що хочете utf8навіть у 3.x. Оновлено відповідь.
Antony Hatchkins

4
О, ви абсолютно праві - я, мабуть, щось переплутав. +1 для деталей.
Фігаг

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!
Blairg23

162

Я відповів би з невеликою модифікацією вищезгаданими відповідями, а це - написати попередньо попереджений файл 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'
stevek

1
@SirBenBenji Переконайтеся, що рядок, яку ви намагаєтеся записати, слід: str.decode ('utf-8').
ambodi

1
@SirBenBenji Ви також можете спробувати використовувати кодеки, як зазначено нижче dinos66
Shiv

Ви також повинні оголосити своє кодування, додавши # -*- coding: utf-8 -*-після shebang
aesede

2
+1 для сортування ключів та відступ. @aesede Недоцільно додавати цей рядок, оскільки це створить враження, що це рішення працює як з python2, так і з ним ( UnicodeEncodeErrorз даними не-ascii). Детальніше див. У моєму рішенні .
Антоні Хеткінс

111

Читання та запис файлів JSON за допомогою Python 2 + 3; працює з unicode

# -*- 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 пробіли для відступу кожного запису, наприклад, коли починається новий дікт (інакше всі будуть в одному рядку),
  • 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прапор Trueза замовчуванням. Ви будете мати нечитабельні 6-байтові "\u20ac"послідовності для кожного у вашому файлі json (як і будь-який інший символ, що не відповідає ascii).
Ентоні Хеткінс

Чому ви використовуєте openдля читання, а не io.openдля письма? Чи можна використовувати і io.openдля читання? Якщо так, то які параметри слід передати?
Міхей Золту

23

Для тих із вас, хто намагається скинути грецькі чи інші "екзотичні" мови, такі як я, але також виникають проблеми (помилки 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))

1
+1 Хоча документи рекомендують python3 вбудований 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.

Щоб проілюструвати це, слідкуйте за відповіддю фігага: код у його відповіді пробивається на 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.


Наведіть причини, коли ви заявляєте, що щось не так. Використовуйте @ nickname, щоб особа отримувала сповіщення. Ви не можете писати коментарі, але ви можете читати коментарі. Як уже було сказано у моїй відповіді на перший коментар, спробуйте data = {'asdf': 1}. Ви отримаєте горезвісний TypeErrorіз своїм (другим) варіантом.
Ентоні Хетчкінс

Щодо ensure_ascii- це необхідно, якщо ви хочете отримати "справжній" результат utf8. Без нього у вас буде звичайна асція з 6 байтами на російську букву, на відміну від 2 байт на символ із цим прапором.
Антоні Хеткінс

@AntonyHatchkins Ви праві для своєї unicode()частини. Я щойно зрозумів для ioпакета в Python 2, write()потребує unicode, ні str.
ibic

1
Цей код працює для мене навіть у python2.6.6, Debian (10 грудня 2010 р.). А також з python2.7.9 або python3. Перевірте ще раз, пл.
Ентоні Хеткінс

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)

цей приклад у списку зберігається у файлі.


подібне, але надайте приклад
Вішал Гедія

5

Щоб написати JSON з відступом, "гарненький друк":

import json

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

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


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блок гарантує, що файл завжди закривається так само, як і блок "спробувати / нарешті", але коротше.
Антоні Хеткінс

3

Запис 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('')

Ласкаво просимо до переповнення стека. Якщо ви вирішите відповісти на старіші запитання, на які є чітко встановлені та правильні відповіді, додавання нової відповіді в кінці дня може не отримати вам жодної заслуги. Якщо у вас є якась нова відмінна інформація, або ви впевнені, що інші відповіді невірні, будь-ласка, додайте нову відповідь, але "ще одна відповідь", що дає ту саму основну інформацію довгий час після того, як запитання, як правило, вигравали " t заробляєш багато кредиту. (Ви показуєте деякі зразкові дані; це добре, але я не впевнений, що цього достатньо, тим більше, що ви не показуєте, що виробляється для вибіркових даних.)
Джонатан Леффлер,

Ok спасибі за інструктивний
іману

2

якщо ви намагаєтесь написати кадр даних панди у файл у форматі json, я рекомендував би це

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

2

Усі попередні відповіді правильні, ось дуже простий приклад:

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

введіть тут опис зображення


1

Прийнята відповідь - це добре. Однак я зіткнувся з помилкою "не json serializable", використовуючи це.

Ось як я це зафіксував open("file-name.json", 'w')як вихід:

output.write(str(response))

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


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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.