2016-02-04 22 views
6

Mit Python 3.5.1 zog ich eine Textdatei, in der jede Zeile in JSON-Form ist: {"a": "windows", "b": "treppen" ...}JSON-Objekt muss str sein, nicht 'Bytes'

import json 
path = 'folder/data.txt' 
records=[json.loads(line) for line in open(path,'rb')] 

aber erhielt ich den Fehler:

the JSON object must be str, not 'bytes' 

ich habe kein Problem die erste Zeile der Datei zu drucken, so dass ich bin beruhigt, dass der Dateipfad richtig ist.

+3

Vielleicht in der 'b' loszuwerden Ihre Offener Anruf? https://docs.python.org/2/library/functions.html#open sagt, dass die Datei in Binärform geladen wird, weshalb sie möglicherweise nicht als Zeichenfolge verwendet wird. – TW80000

+0

Wenn Sie nur eine Zeile der Datei nehmen, können Sie sie in json laden? Wie 'json.loads (file.readlines() [0])' –

+0

@ TW80000 löst Ihr Vorschlag mein Problem. Ich habe auch gelernt, dass es auch möglich ist, 'encoding = 'utf-8'' direkt im' open'-Call zu übergeben. Danke für deinen Kommentar. – Greg

Antwort

3

Öffnen Sie die Datei im Textmodus, nicht im Binärmodus (möglicherweise wird encoding='utf-8' explizit übergeben, um den Systemstandard zu überschreiben, da JSON normalerweise als UTF-8 gespeichert wird). Das json Modul nimmt nur str Eingang; aus einer Datei im Binär-Modus zurück bytes Objekte geöffnet Lesen:

# Using with statement just for good form; in this case it would work the 
# same on CPython, but on other interpreters or different CPython use cases, 
# it's easy to screw something up; use with statements all the time to build good habits 
with open(path, encoding='utf-8') as f: 
    records=[json.loads(line) for line in f] 
+0

Das funktioniert und ich danke Ihnen für den Rat zur Verwendung der richtigen Form. Das Umschalten von 'rb' für 'encoding =' utf-8 'in meinem ursprünglichen Code scheint ebenfalls zu funktionieren. – Greg

1

Sie wollen nicht angeben „rb“, da binäre Darstellung der Datei sein würde lesbar durch das JSON-Modul nicht. Sie möchten wahrscheinlich "utf-8" Codierung und "lesen". EDIT: Ich hatte ursprünglich gesagt, dass beide Standards sind, aber es wurde mir zur Kenntnis gebracht, dass viele Betriebssysteme unterschiedliche Standardcodierung haben und dass Python die Systemeinstellung als Standard in open() verwendet. Ich würde daher empfehlen, die Einstellung für die Codierung explizit als "utf-8" anzugeben.

json unterstützt das Laden von einer geöffneten Datei mit "json.load" anstelle von "json.loads", die von einer Zeichenkette geladen wird, so dass wir den eingelesenen Text überspringen und direkt zu JSON gehen können. Ich glaube nicht, dass Sie einzelne Zeilen "laden" wollen, da dies wahrscheinlich kein gültiger JSON ist.

import json 
# open has __enter__ and __exit__ functions, so we can call it as a guard 
# using "with" syntax and it'll close when the scope ends 
with open(r".\myjson.json", encoding="utf-8") as fh: 
    # load() is a convenience function to help us avoid iterating lines 
    # on our own. It calls loads() on the whole doc and returns an obj 
    json_obj = json.load(fh) 
print (json_obj) 
+1

UTF-8 ist nicht immer der Standard 'encoding', [wird dynamisch von plattformabhängigen Einstellungen mit' locale.getpreferredencoding (False) '' bestimmt (https://docs.python.org/3/library/functions.html#) öffnen). Wenn Sie wissen, dass die Eingabe UTF-8 ist, sagen Sie dies explizit. Wenn jemand JSON-Blobs einmal pro Zeile geschrieben hat, kann man nicht die gesamte Datei auf einmal laden, weil die gesamte Datei nicht gültig ist. JSON, die Zeilen sind nur legale JSON-Dateien isoliert. Außerdem ruft 'json.load' nur' file.read() 'auf und geht zu' loads', also ist es weder besser noch schlechter als 'loads'. Außerdem benötigt Py3 'print' Parens. – ShadowRanger

+0

große Punkte, @ShadowRanger. Für load() vs loads() wollte ich nicht implizieren, dass es hier eine Leistungslücke gibt, sondern dass es eine for-Schleife gibt, die wir nicht in unserem eigenen Code schreiben/lesen/pflegen müssen. Die Verwendung von load() hat weniger Rauschen, was normalerweise der pythonische Weg ist, Dinge zu tun. Der Druck war ich in einem 2,7-Dolmetscher (meine schlechte und feste). Die UTF-8 denken, dass du völlig richtig liegst und ich hätte das mit Windows voranbringen sollen (nicht unbedingt OPs Fall). –

+0

Eigentlich, unter Windows, glaube ich nicht, dass UTF-8 der Standard ist, es ist normalerweise eine der Windows-Codepages (zB cp1252, eine Variante von latin-1, die einige der normalerweise unbenutzten Steuerzeichen durch zusätzliche druckbare Zeichen ersetzt. zB intelligente Zitate).Wenn es sich bei den Daten um ASCII handelt, dann geht es Ihnen gut (sowohl UTF-8 als auch cp1252 sind ASCII-Obermengen). Nur wenn Sie außerhalb des ASCII-Bereichs liegen, haben Sie Probleme. Abgesehen von den Codepages verwendet Windows normalerweise UTF-16 für alles; es akzeptiert nur UTF-8, wenn es um Daten im Internet geht (wobei UTF-8 der Standard ist). – ShadowRanger

2

Versuchen: Datensätze = [json.loads (. Linie decode()) für Linie in offenen (path, 'rb')]

Verwandte Themen