JSON verilerini bir dosyaya nasıl yazarım?


1122

Değişkende saklanan JSON verileri var data.

Her seferinde sunucudan veri almak zorunda kalmamak için test için bir metin dosyasına yazmak istiyorum.

Şu anda bunu deniyorum:

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

Ve bu hatayı alıyorum:

TypeError: dikte değil dize veya arabellek olmalıdır

Bunu nasıl düzeltirim?

Yanıtlar:


2040

Gerçek JSON bölümünü unuttun - databir sözlük ve henüz JSON kodlu değil. Bunu yaz böyle Maksimum uyumluluk (Python 2 ve 3) için:

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

Modern bir sistemde (yani Python 3 ve UTF-8 desteği) ile daha güzel bir dosya yazabilirsiniz.

import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)

8
bu serileştirme için yararlı olabilir: stackoverflow.com/questions/4512982/…
jedierikb

12
Şunu mu demek istediniz: json.dump veya json.dumps?
TerminalDilettante

153
@TerminalDilettante json.dumpbir dosyaya veya dosya benzeri bir nesneye yazar, json.dumpsbir dize döndürür.
phihag

24
btw: veriyi yeniden okumak için: infile olarak open ('data.txt') ile: d = json.load (infile). Bakınız: bu cevap
klaas

9
@ denvar Hayır, bu cevap hassas bir şekilde ayarlandı. Python 3'te, json.dumpikili bir dosyaya değil, bir metin dosyasına yazar. TypeErrorDosya açılırsa bir alırsınız wb. Eski Python sürümlerinde, hem wNAND wbçalışması. json.dumpYalnızca varsayılan olarak ASCII olduğu için açık bir kodlama gerekli değildir . Kodunuzun hiçbir zaman eski Python sürümlerinde çalışmadığından emin olabilirseniz ve siz ve JSON dosyasının işleyicisi ASCII dışı verileri doğru şekilde işleyebilir, birini belirleyebilir ve ayarlayabilirsiniz ensure_ascii=False.
phihag

267

Almak için utf8 kodlanmış aksine dosyayı ASCII kodlanmış Python 2 kullanılmak üzere kabul edilen yanıtında:

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

Python 3'te kod daha basit:

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

Windows'da encoding='utf-8'argümanı openhala gereklidir.

Verilerin kodlanmış bir kopyasını bellekte (sonucu dumps) saklamaktan kaçınmak ve hem Python 2 hem de 3'te utf8 kodlu bayt dizileri çıkarmak için şunu kullanın:

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

codecs.getwriterÇağrı Python 3'te gereksiz ama Python 2 için gerekli olan


Okunabilirlik ve boyut:

Kullanımı ensure_ascii=Falsedaha iyi okunabilirlik ve daha küçük boyut sağlar:

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

Daha bayraklar ekleyerek okunabilirliği artırmak indent=4, sort_keys=True(aynı önerdiği dinos66 argümanları) dumpveya dumps. Bu şekilde, biraz daha büyük bir dosya boyutu pahasına json dosyasında güzel girintili sıralanmış bir yapı elde edersiniz.


5
Bu unicodegereksizdir - sonucu json.dumpszaten bir unicode nesnesidir. Bunun, çıkış dosyası modunun tüm karmaşasının temizlendiği 3.x'te başarısız olduğunu ve json'un her zaman karakter dizeleri (ve karakter G / Ç) kullandığını ve asla bayt kullanmadığını unutmayın.
phihag

4
2.x type(json.dumps('a'))içinde <type 'str'>. Hatta type(json.dumps('a', encoding='utf8'))olduğunu <type 'str'>.
Antony Hatchkins

4
Evet, 3.x json dizeleri kullanır, ancak varsayılan kodlama ascii. Bunu açıkça utf83.x'de bile istediğinizi söylemelisiniz . Yanıt güncellendi.
Antony Hatchkins

4
Oh, tamamen haklısın - bir şeyleri karıştırmalıydım. Detay için +1.
phihag

1
2.7 kullanmama rağmen Python 3.x yanıtı benim için çalıştı. 2.x cevap hata döndürdü: 'ascii' codec can't decode byte 0xf1 in position 506755: ordinal not in range(128). Şüphe duyduğunuzda 3.x yanıtını kullanın!
Blairg23

162

Yukarıda belirtilen cevaplarla hafif bir değişiklikle cevap verirdim ve bu, insan gözlerinin daha iyi okuyabileceği önceden hazırlanmış bir JSON dosyası yazmak. Bunun için geçmesi sort_keysolarak Trueve indent4 boşluk karakterleri ile ve gitmek iyidir. Ayrıca ascii kodlarının JSON dosyanıza yazılmamasına dikkat edin:

with open('data.txt', 'w') as outfile:
     json.dump(jsonData, outfile, sort_keys = True, indent = 4,
               ensure_ascii = False)

2
hala eldeUnicodeEncodeError: 'ascii' codec can't encode character u'\xfc'
stevek

1
@SirBenBenji Yazmaya çalıştığınız dizenin şu şekilde olduğundan emin olun: str.decode ('utf-8').
ambodi

1
@SirBenBenji Dinos66'nın aşağıda belirttiği gibi kodekleri de deneyebilirsiniz
Shiv

Ayrıca # -*- coding: utf-8 -*-shebang sonra ekleyerek kodlama ilan etmek zorunda
aesede

2
Sort_keys ve girinti için +1. @aesede Bu satırı eklemek iyi değildir, çünkü bu çözümün python2 UnicodeEncodeErrorile ( ascii olmayan verilerle) de çalışmadığı izlenimini verecektir . Bkz benim çözüm detayları için.
Antony Hatchkins

111

Python 2 + 3 ile JSON dosyalarını okuma ve yazma; unicode ile çalışır

# -*- 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)

Parametrelerin açıklaması json.dump:

  • indent: Her girişi girintilemek için 4 boşluk kullanın, örneğin yeni bir diksiyon başlatıldığında (aksi takdirde tümü bir satırda olacaktır),
  • sort_keys: sözlüklerin anahtarlarını sıralar. Json dosyalarını bir diff aracıyla karşılaştırmak / sürüm kontrolü altına almak istiyorsanız bu yararlıdır.
  • separators: Python'un arka boşluklar eklemesini önlemek için

Bir paket ile

mpuSüper basit ve hatırlaması kolay bir tane için yardımcı program paketine bir göz atın :

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

JSON dosyası oluşturuldu

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

Ortak dosya sonları

.json

Alternatifler

Başvurunuz için aşağıdakiler önemli olabilir:

  • Diğer programlama dillerinin desteği
  • Okuma / yazma performansı
  • Kompaktlık (dosya boyutu)

Ayrıca bkz: Veri serileştirme formatlarının karşılaştırılması

Yapılandırma dosyaları oluşturmanın bir yolunu arıyorsanız , Python'daki yapılandırma dosyamdaki kısa makalemi okumak isteyebilirsiniz.


2
Not force_asciibayrağıdır Truevarsayılan olarak. Json dosyanızdaki (ve diğer ascii olmayan karakterlerin) "\u20ac"her biri için okunamayan 6 baytlık dizilere sahip olacaksınız .
Antony Hatchkins

Neden openokumak için ama io.openyazmak için kullanıyorsunuz? Öyle mi mümkün kullanımı io.openyanı okumak için? Eğer öyleyse, hangi parametreler geçirilmelidir?
Micah Zoltu

23

Yunanca veya benim gibi diğer "egzotik" dilleri boşaltmaya çalışan ama aynı zamanda barış sembolü (\ u262E) gibi garip karakterlerle veya genellikle json formlu verilerinde bulunan diğerleriyle ilgili sorunlar (unicode hataları) olanlarınız için Twitter gibi, çözüm aşağıdaki gibi olabilir (sort_keys açıkça isteğe bağlıdır):

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 dokümanlar python3 yerleşiğini tavsiye ettiği halde openve assotiated io.openüzerinde codecs.openayrıca güzel bir geriye dönük uyumluluk kesmek bu durumda. Python2'de io.open'den codecs.opendaha "omnivordur" (gerekirse, hem str hem de unicode "yiyebilir"). Bu codecs.opentuhaflık , girişteki unicode dizelerin varlığına bağlı olarak json.dumpsfarklı nesne türleri ( str/ unicode) üretme tuhaflığını telafi edebilir .
Antony Hatchkins

10

Yorum eklemek için yeterli üne sahip değilim, bu yüzden bu sinir bozucu TypeError hakkındaki bazı bulgularımı burada yazıyorum:

Temelde, ben sadece json.dump()Python 2 işlevinde bir hata olduğunu düşünüyorum - ASCII olmayan karakterler içeren bir Python (sözlük / liste) veri dökümü olamaz, hattaencoding = 'utf-8' parametre ile dosyayı açın . (yani ne yaparsanız yapın). Ancak, json.dumps()hem Python 2 hem de 3 üzerinde çalışır.

Hariç olmak üzere Python 2'de onun cevabı sonları kodu: phihag yanıtını takip etmek, bu göstermek için TypeError: must be unicode, not strise, dataASCII olmayan karakterler içeriyor. (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)

Ancak Python 3'te iyi çalışıyor.


Bir şeyin yanlış olduğunu iddia ettiğinizde sebep verin. Kişinin bilgilendirilmesi için @ nickadı kullanın. Yorum yazamazsınız, ancak yorumları okuyabilirsiniz. İlk yoruma verilen cevabımda belirtildiği gibi, deneyin data = {'asdf': 1}. Sen TypeError(ikinci) varyant ile kötü şöhretli alacak .
Antony Hatchkins

İlgili ensure_ascii- "gerçek" bir utf8 çıkışı almak istiyorsanız gereklidir. Bu olmadan, bu bayrakla karakter başına 2 bayt yerine, rus harf başına 6 baytlık sade ascii'ye sahip olacaksınız.
Antony Hatchkins

@AntonyHatchkins Bu parça için haklısın unicode(). ioPython 2'deki paket için yeni farkettim , write()ihtiyaçları unicodedeğil str.
ibic

1
Bu kod python2.6.6, Debian (10 Aralık 2010) ile bile benim için çalışıyor. Python2.7.9 veya python3 ile birlikte. Bir kez daha kontrol et, lütfen.
Antony Hatchkins

7

JSON kullanarak dosyaya veri yazın, kullanılan json.dump () veya json.dumps () kullanın. verileri dosyada saklamak için böyle yazın.

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

listedeki bu örnek bir dosyaya depolanır.


benzer ancak örnek verin
Vishal Gediya

5

JSON'u girinti ile yazmak için "pretty print":

import json

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

Ayrıca, yanlış biçimlendirilmiş JSON'da hata ayıklamanız ve faydalı bir hata iletisi istiyorsanız, import simplejsonkitaplık kullanın import json(işlevler aynı olmalıdır)


4
json.dump(data, open('data.txt', 'wb'))

2
Bu, @ phihag'ın cevabı ile aynı şeyi yapar, ancak her zaman çalışacağı garanti edilmez. Böyle kodu göz önünde bulundurun: f = open('1.txt', 'w'); f.write('a'); input(). Çalıştırın ve sonra SYGTERM (Ctrl-Z daha sonra kill %1Linux'ta, Ctrl-BreakWindows'ta). 1.txt0 bayt olacaktır. Bunun nedeni, yazının arabelleğe alınmış olması ve dosyanın SYGTERM oluştuğu anda kapatılmamasıdır. withblock, dosyanın 'try / nihayet' bloğunun yaptığı gibi her zaman kapanmasını ancak daha kısa olmasını garanti eder.
Antony Hatchkins

3

Bir Dosyaya JSON Yazma

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)

Bir Dosyadan JSON Okuma

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('')

Stack Overflow'a hoş geldiniz. İyi kurulmuş ve doğru cevapları olan daha eski bir soruyu cevaplamaya karar verirseniz, günün geç saatlerinde yeni bir yanıt eklemek size herhangi bir kredi getirmeyebilir. Bazı farklı yeni bilgileriniz varsa veya diğer cevapların yanlış olduğuna ikna olduysanız, elbette yeni bir cevap ekleyin, ancak aynı soruya genellikle sorulduktan uzun bir süre sonra aynı temel bilgileri veren 'yine başka bir cevap' kazandı ' Sana çok fazla kredi kazandırmaz. (Bazı örnek verileri gösterirsiniz; bu iyi, ancak özellikle örnek veriler için neyin üretildiğini göstermediğiniz için bunun yeterli olduğundan emin değilim.)
Jonathan Leffler

Tamam rehberlik için teşekkürler
iman

2

json biçimini kullanarak bir dosyaya pandalar veri çerçevesi yazmaya çalışıyorsanız bunu tavsiye ederim

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

2

Önceki tüm cevaplar doğrudur burada çok basit bir örnek:

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

resim açıklamasını buraya girin


1

Kabul edilen cevap iyidir. Ancak, ben bunu kullanarak "json serileştirilebilir değil" hatası içine koştu.

İşte nasıl open("file-name.json", 'w')çıktı olarak sabit :

output.write(str(response))

Oluşturduğu json dosyası olarak iyi bir düzeltme olmamasına rağmen çift tırnak olmayacak, ancak hızlı ve kirli arıyorsanız harika.


0

JSON verileri bir dosyaya aşağıdaki gibi yazılabilir

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]}]

Bir dosyaya yazın:

with open('text1.json', 'w') as f:
     json.dump(hist1, f)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.