2016-02-04 22 views
6

Utilizzando Python 3.5.1, ho inserito un file di testo in cui ogni riga è in formato JSON: {"a": "windows", "b": "stairs" ...}L'oggetto JSON deve essere str, non 'byte'

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

ma ho ricevuto l'errore:

the JSON object must be str, not 'bytes' 

non ho la stampa della prima riga del file problema, quindi sono rassicurato che il percorso del file sia corretto.

+3

Forse sbarazzarsi del 'b' nella vostra chiamata 'open'? https://docs.python.org/2/library/functions.html#open dice che caricherà il file in formato binario, il che potrebbe essere il motivo per cui non viene preso come una stringa. – TW80000

+0

Se si prende solo una riga del file, è possibile caricarlo su json? Come 'json.loads (file.readlines() [0])' –

+0

@ TW80000 il tuo suggerimento risolve il mio problema. Ho anche imparato che passare 'encoding = 'utf-8'' direttamente nella chiamata' open' funziona pure. Grazie per il tuo commento. – Greg

risposta

3

Apre il file in modalità testo, non in modalità binaria (è possibile passare esplicitamente a encoding='utf-8' per ignorare l'impostazione predefinita di sistema, poiché JSON viene solitamente memorizzato come UTF-8). Il modulo json richiede solo l'input str; la lettura da un file aperto in modalità binaria ritorna bytes oggetti:

# 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

Questo funziona e ti ringraziamo per il consiglio sull'utilizzo di un modulo corretto. Cambiare 'rb' out per 'encoding =' utf-8 'nel mio codice originale sembra funzionare bene. – Greg

1

Se non si desidera specificare "rb", dal momento che la rappresentazione binaria del file non sarà leggibile dal modulo JSON. Probabilmente vuoi la codifica "utf-8" e "leggi". EDIT: Originariamente avevo detto che entrambi erano predefiniti, ma è stato portato alla mia attenzione che molti SO hanno differenti codifiche predefinite e che Python usa le impostazioni di sistema come predefinite in open(). Raccomanderei quindi di fornire esplicitamente l'impostazione di codifica come "utf-8".

json supporta il caricamento da un file aperto con "json.load" anziché "json.loads", che viene caricato da una stringa, in modo che possiamo saltare il read-in-come-testo e andare direttamente a JSON. Non penso che vorrai "caricare" singole righe, poiché probabilmente non sarà un JSON valido.

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 non è sempre la 'codifica' predefinita, [è determinata dinamicamente dalle impostazioni dipendenti dalla piattaforma usando' locale.getpreferredencoding (False) '] (https://docs.python.org/3/library/functions.html# Aperto). Se sai che l'input è UTF-8, dillo in modo esplicito. Allo stesso modo, se qualcuno ha scritto blob JSON un per linea, non è possibile caricare l'intero file in una volta, perché l'intero file preso insieme non è JSON valido, le linee sono solo JSON legali isolate. Inoltre, 'json.load' chiama semplicemente' file.read() 'e passa a' loads', quindi non è né meglio né peggio di 'loads'. Inoltre, Py3 'print' ha bisogno di paren. – ShadowRanger

+0

ottimi punti, @ShadowRanger. Per load() vs loads(), non volevo implicare che ci fosse un gap di prestazioni qui, ma che c'è un ciclo for che non abbiamo bisogno di scrivere/leggere/mantenere nel nostro codice. L'uso di load() ha meno rumore, che di solito è il modo pitone di fare le cose. La stampa mi stava lavorando in un interprete 2.7 (il mio male e fisso). L'UTF-8 pensa che tu abbia perfettamente ragione e avrei dovuto farlo con Windows (non necessariamente il caso dell'OP). –

+0

In realtà, su Windows, non penso che UTF-8 sia l'impostazione predefinita, di solito è una delle tabelle codici di Windows (ad esempio cp1252, una variazione su latin-1 che sostituisce alcuni dei caratteri di controllo solitamente inutilizzati con caratteri stampabili aggiuntivi, es. virgolette intelligenti).Se i dati erano tutti ASCII, allora sei a posto (entrambi UTF-8 e cp1252 sono superset ASCII), è solo quando raggiungi l'intervallo ASCII che avresti problemi. A parte le code page, Windows usa solitamente UTF-16 per tutto; accetta solo UTF-8 quando si tratta di dati su Internet (dove UTF-8 è lo standard). – ShadowRanger

2

Prova: record = [json.loads (. linea di decodifica()) per la linea in aperto (percorso, 'rb')]

Problemi correlati