Wie schreibe ich JSON-Daten in eine Datei?

1122

Ich habe JSON-Daten in der Variablen gespeichert data.

Ich möchte dies zum Testen in eine Textdatei schreiben, damit ich nicht jedes Mal die Daten vom Server abrufen muss.

Derzeit versuche ich Folgendes:

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

Und ich erhalte diesen Fehler:

TypeError: muss Zeichenfolge oder Puffer sein, nicht diktieren

Wie kann ich das beheben?

user1530318
quelle

Antworten:

2041

Sie haben den eigentlichen JSON-Teil vergessen - dataist ein Wörterbuch und noch nicht JSON-codiert. Schreiben Sie es für maximale Kompatibilität wie folgt (Python 2 und 3):

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

Auf einem modernen System (dh Python 3- und UTF-8-Unterstützung) können Sie eine schönere Datei mit schreiben

import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)
Phihag
quelle
8
Dies könnte für die Serialisierung hilfreich sein: stackoverflow.com/questions/4512982/…
jedierikb
12
Meinen Sie json.dump oder json.dumps?
TerminalDilettante
153
@TerminalDilettante json.dumpschreibt in eine Datei oder ein dateiähnliches Objekt, während json.dumpseine Zeichenfolge zurückgegeben wird.
Phihag
24
Übrigens: Um die Daten erneut zu lesen, verwenden Sie: mit open ('data.txt') als infile: d = json.load (infile). Siehe: diese Antwort
klaas
9
@denvar Nein, diese Antwort ist fein abgestimmt. json.dumpSchreibt unter Python 3 in eine Textdatei, nicht in eine Binärdatei. Sie würden eine erhalten, TypeErrorwenn die Datei mit geöffnet wurde wb. Bei älteren Python-Versionen wfunktionieren beide nand wb. Eine explizite Codierung ist nicht erforderlich, da die Ausgabe json.dumpvon standardmäßig nur ASCII ist. Wenn Sie sicher sein können, dass Ihr Code niemals in älteren Python-Versionen ausgeführt wird und Sie und der Handler der JSON-Datei Nicht-ASCII-Daten korrekt verarbeiten können, können Sie eine angeben und festlegen ensure_ascii=False.
Phihag
267

Um UTF - 8 - kodierte Datei im Gegensatz zu ascii - codiertes in der akzeptierten Antwort für Python 2 Verwendung:

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

Der Code ist in Python 3 einfacher:

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

Unter Windows ist das encoding='utf-8'Argument to openweiterhin erforderlich.

Verwenden Sie Folgendes, um zu vermeiden, dass eine codierte Kopie der Daten im Speicher gespeichert wird (Ergebnis von dumps) und utf8-codierte Bytestrings in Python 2 und 3 auszugeben.

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

Der codecs.getwriterAufruf ist in Python 3 redundant, für Python 2 jedoch erforderlich


Lesbarkeit und Größe:

Die Verwendung von ensure_ascii=Falsebietet eine bessere Lesbarkeit und eine kleinere Größe:

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

Weitere Verbesserung der Lesbarkeit durch Hinzufügen von Flags indent=4, sort_keys=True(wie von dinos66 vorgeschlagen ) zu Argumenten von dumpoder dumps. Auf diese Weise erhalten Sie eine gut eingerückte sortierte Struktur in der JSON-Datei auf Kosten einer etwas größeren Datei.

Antony Hatchkins
quelle
5
Das unicodeist überflüssig - das Ergebnis von json.dumpsist bereits ein Unicode-Objekt. Beachten Sie, dass dies in 3.x fehlschlägt, wo das gesamte Durcheinander des Ausgabedateimodus bereinigt wurde und json immer Zeichenfolgen (und Zeichen-E / A) und niemals Bytes verwendet.
Phihag
4
In 2.x type(json.dumps('a'))ist <type 'str'>. Auch type(json.dumps('a', encoding='utf8'))ist <type 'str'>.
Antony Hatchkins
4
Ja, in 3.x verwendet json Zeichenfolgen, die Standardcodierung lautet jedoch ascii. Sie müssen explizit angeben, dass Sie utf8auch in 3.x wollen . Die Antwort wurde aktualisiert.
Antony Hatchkins
4
Oh, du hast vollkommen recht - ich muss etwas verwirrt haben. +1 für das Detail.
Phihag
1
Die Python 3.x-Antwort hat bei mir funktioniert, obwohl ich 2.7 verwende. Die 2.x-Antwort hat einen Fehler zurückgegeben : 'ascii' codec can't decode byte 0xf1 in position 506755: ordinal not in range(128). Verwenden Sie im Zweifelsfall die 3.x-Antwort!
Blairg23
162

Ich würde mit geringfügigen Änderungen mit den oben genannten Antworten antworten und das heißt, eine hübsche JSON-Datei schreiben, die das menschliche Auge besser lesen kann. Übergeben Sie dies sort_keysals Trueund indentmit 4 Leerzeichen und Sie können loslegen. Stellen Sie außerdem sicher, dass die ASCII-Codes nicht in Ihre JSON-Datei geschrieben werden:

with open('data.txt', 'w') as outfile:
     json.dump(jsonData, outfile, sort_keys = True, indent = 4,
               ensure_ascii = False)
ambodi
quelle
2
immer nochUnicodeEncodeError: 'ascii' codec can't encode character u'\xfc'
stevek
1
@SirBenBenji Stellen Sie sicher, dass die Zeichenfolge, die Sie schreiben möchten, wie folgt lautet: str.decode ('utf-8').
Ambodi
1
@ SirBenBenji Sie können auch versuchen, Codecs zu verwenden, wie dinos66 unten angibt
Shiv
Sie müssen auch Ihre Kodierung deklarieren, indem Sie # -*- coding: utf-8 -*-nach dem
shebang
2
+1 für sort_keys und Einzug. @aesede Es ist nicht gut, diese Zeile hinzuzufügen, da dadurch der Eindruck entsteht, dass diese Lösung auch mit Python2 funktioniert, was nicht der Fall ist ( UnicodeEncodeErrormit Nicht-ASCII-Daten). Siehe meine Lösung für Details.
Antony Hatchkins
111

Lesen und Schreiben von JSON-Dateien mit Python 2 + 3; funktioniert mit 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)

Erläuterung der Parameter von json.dump:

  • indent: Verwenden Sie 4 Leerzeichen, um jeden Eintrag einzurücken, z. B. wenn ein neues Diktat gestartet wird (andernfalls werden alle in einer Zeile stehen).
  • sort_keys: sortiere die Schlüssel der Wörterbücher. Dies ist nützlich, wenn Sie JSON-Dateien mit einem Diff-Tool vergleichen / unter Versionskontrolle stellen möchten.
  • separators: Um zu verhindern, dass Python nachgestellte Leerzeichen hinzufügt

Mit einem Paket

Schauen Sie sich mein Dienstprogramm an, mpuum ein supereinfaches und leicht zu merkendes zu erhalten:

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

JSON-Datei erstellt

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

Allgemeine Dateienden

.json

Alternativen

Für Ihre Anwendung kann Folgendes wichtig sein:

  • Unterstützung durch andere Programmiersprachen
  • Lese- / Schreibleistung
  • Kompaktheit (Dateigröße)

Siehe auch: Vergleich der Datenserialisierungsformate

Wenn Sie eher nach einer Möglichkeit suchen, Konfigurationsdateien zu erstellen, lesen Sie möglicherweise meinen kurzen Artikel Konfigurationsdateien in Python

Martin Thoma
quelle
2
Beachten Sie, dass das force_asciiFlag Truestandardmäßig ist. Sie haben unlesbare 6-Byte- "\u20ac"Sequenzen für jede in Ihrer JSON-Datei (sowie für jedes andere Nicht-ASCII-Zeichen).
Antony Hatchkins
Warum verwenden Sie openzum Lesen, aber io.openzum Schreiben? Kann man es auch zum io.openLesen verwenden? Wenn ja, welche Parameter sollten übergeben werden?
Micah Zoltu
23

Für diejenigen unter Ihnen, die versuchen, Griechisch oder andere "exotische" Sprachen wie mich zu löschen, aber auch Probleme (Unicode-Fehler) mit seltsamen Zeichen wie dem Friedenssymbol (\ u262E) oder anderen haben, die häufig in json-formatierten Daten enthalten sind Bei Twitter könnte die Lösung wie folgt aussehen (sort_keys ist offensichtlich optional):

import codecs, json
with codecs.open('data.json', 'w', 'utf8') as f:
     f.write(json.dumps(data, sort_keys = True, ensure_ascii=False))
dinos66
quelle
1
+1 Während docs Python3 Builtin openund das Assoziated io.openOver empfiehlt codecs.open, ist es in diesem Fall auch ein netter abwärtskompatibler Hack. In Python2 codecs.openist es "alles fressender" als io.open (es kann sowohl str als auch unicode "essen" und bei Bedarf konvertieren). Man kann sagen, dass diese codecs.openEigenart die json.dumpsEigenart der Erzeugung verschiedener Objekttypen ( str/ unicode) in Abhängigkeit vom Vorhandensein der Unicode-Zeichenfolgen in der Eingabe kompensiert .
Antony Hatchkins
10

Ich habe nicht genug Ruf, um Kommentare hinzuzufügen, deshalb schreibe ich hier nur einige meiner Ergebnisse dieses nervigen TypeError:

Grundsätzlich denke ich, dass es nur json.dump()in Python 2 ein Fehler in der Funktion ist - es kann keine Python-Daten (Wörterbuch / Liste) ausgeben, die Nicht-ASCII-Zeichen enthalten, selbst wenn Sie die Datei mit dem encoding = 'utf-8'Parameter öffnen . (dh egal was du tust). Funktioniert jedoch json.dumps()sowohl mit Python 2 als auch mit Python 3.

Um dies zu veranschaulichen, folgen Sie der Antwort von phihag: Der Code in seiner Antwort bricht in Python 2 mit Ausnahme TypeError: must be unicode, not str, wenn er dataNicht-ASCII-Zeichen enthält. (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)

In Python 3 funktioniert es jedoch einwandfrei.

ibic
quelle
Begründen Sie, wenn Sie behaupten, etwas sei falsch. Verwenden Sie @nickname, damit die Person benachrichtigt wird. Sie können keine Kommentare schreiben, aber Sie können Kommentare lesen. Wie bereits in meiner Antwort auf den ersten Kommentar angegeben, versuchen Sie es data = {'asdf': 1}. TypeErrorMit Ihrer (zweiten) Variante werden Sie berüchtigt .
Antony Hatchkins
Betroffen ensure_ascii- es ist notwendig, wenn Sie eine "echte" utf8-Ausgabe erhalten möchten. Ohne sie haben Sie einfache ASCII mit 6 Bytes pro russischem Buchstaben im Gegensatz zu 2 Bytes pro Zeichen mit dieser Flagge.
Antony Hatchkins
@AntonyHatchkins Sie sind für das unicode()Teil richtig . Ich habe gerade für ioPaket in Python 2 realisiert, write()braucht unicode, nicht str.
ibic
1
Dieser Code funktioniert für mich sogar mit python2.6.6, Debian (10. Dezember 2010). Sowie mit python2.7.9 oder python3. Überprüfen Sie es noch einmal, bitte.
Antony Hatchkins
7

Schreiben Sie Daten in eine Datei mit JSON. Verwenden Sie dazu json.dump () oder json.dumps () . Schreiben Sie so, um Daten in einer Datei zu speichern.

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

Dieses Beispiel in der Liste wird in einer Datei gespeichert.

Vishal Gediya
quelle
es ist ähnlich, aber geben Sie mit Beispiel
Vishal Gediya
5

Um den JSON mit Einrückung zu schreiben, "hübscher Druck":

import json

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

Wenn Sie nicht ordnungsgemäß formatiertes JSON debuggen müssen und eine hilfreiche Fehlermeldung erhalten möchten, verwenden Sie import simplejsonstattdessen die Bibliothek anstelle von import json(Funktionen sollten identisch sein).

James Wierzba
quelle
4
json.dump(data, open('data.txt', 'wb'))
Alexander
quelle
2
Dies entspricht der Antwort von @ phihag, funktioniert jedoch nicht immer garantiert. Betrachten Sie einen solchen Code : f = open('1.txt', 'w'); f.write('a'); input(). Führen Sie es aus und SYGTERMIEREN Sie es ( Ctrl-Zdann kill %1unter Linux, Ctrl-Breakunter Windows). 1.txtwird 0 Bytes haben. Dies liegt daran, dass das Schreiben gepuffert wurde und die Datei zum Zeitpunkt des Auftretens von SYGTERM weder geleert noch geschlossen wurde. withDer Block garantiert, dass die Datei immer geschlossen wird, genau wie der Block 'try / finally', jedoch kürzer.
Antony Hatchkins
3

JSON in eine Datei schreiben

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 aus einer Datei lesen

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('')
Iman
quelle
Willkommen bei Stack Overflow. Wenn Sie sich entscheiden, eine ältere Frage zu beantworten, die gut etablierte und korrekte Antworten enthält, erhalten Sie möglicherweise keine Gutschrift, wenn Sie spät am Tag eine neue Antwort hinzufügen. Wenn Sie einige unverwechselbare neue Informationen haben oder davon überzeugt sind, dass die anderen Antworten alle falsch sind, fügen Sie auf jeden Fall eine neue Antwort hinzu, aber "noch eine Antwort", die die gleichen grundlegenden Informationen lange nach dem Stellen der Frage enthält, ist normalerweise gewonnen. " Ich verdiene dir nicht viel Kredit. (Sie zeigen einige Beispieldaten; das ist gut, aber ich bin nicht sicher, ob es ausreicht, zumal Sie nicht zeigen, was für die Beispieldaten produziert wird.)
Jonathan Leffler
Ok, danke für die Anleitung
iman
2

Wenn Sie versuchen, einen Pandas-Datenrahmen im JSON-Format in eine Datei zu schreiben, würde ich dies empfehlen

destination='filepath'
saveFile = open(destination, 'w')
saveFile.write(df.to_json())
saveFile.close()
Franco Miguel Contreras
quelle
2

Alle vorherigen Antworten sind hier richtig. Dies ist ein sehr einfaches Beispiel:

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

Geben Sie hier die Bildbeschreibung ein

grepit
quelle
1

Die akzeptierte Antwort ist in Ordnung. Allerdings bin ich dabei auf den Fehler "Ist nicht json serialisierbar" gestoßen.

So habe ich es open("file-name.json", 'w')als Ausgabe behoben :

output.write(str(response))

Obwohl es keine gute Lösung ist, da die von ihr erstellte JSON-Datei keine doppelten Anführungszeichen enthält, ist es großartig, wenn Sie schnell und schmutzig suchen.

Akshat Bajaj
quelle
0

Die JSON-Daten können wie folgt in eine Datei geschrieben werden

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

In eine Datei schreiben:

with open('text1.json', 'w') as f:
     json.dump(hist1, f)
Ashok Kumar Jayaraman
quelle