2014-12-26 9 views
5

Sono relativamente nuovo a Python. Sto cercando di leggere un file ASCII con più dizionari al suo interno. Il file ha il seguente formato.come leggere più dizionari da un file in python?

{Key1: value1 
key2: value2 
... 
} 
{Key1: value1 
key2: value2 
... 
} 
{ 
... 

Ogni dizionario nel file è un dizionario nidificato. Sto provando a leggerlo come un elenco di dizionari. c'è un modo semplice per farlo? ho provato il seguente codice ma non sembra funzionare

data = json.load(open('doc.txt')) 
+2

Che errore ottieni? – Mhmd

risposta

1

Dovrete mettere in un grande elenco al fine di ottenere il lavoro. vale a dire

[ 
    {key1: val1, key2: val2, key3: val3, ...keyN: valN} 
    , {key1: val1, key2: val2, key3: val3, ...keyN: valN} 
    , {key1: val1, key2: val2, key3: val3, ...keyN: valN} 
    . 
    . 
    . 
] 

Se non è possibile modificare il formato del file di dati, temo che dovrete rotolare la propria funzione di interpretare i dati.

+0

Non funzionerà. Non ci sono virgole tra i dizionari. Non ci sono virgole tra coppie chiave-valore in un dizionario. – SuperSaiyan

1

Se gli elementi interni sono JSON validi, quanto segue potrebbe funzionare. Ho scovato lo source of simplejson library e l'ho modificato per adattarlo al tuo caso d'uso. Un SSCCE è sotto.

import re 
import simplejson 

FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL 
WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS) 

def grabJSON(s): 
    """Takes the largest bite of JSON from the string. 
     Returns (object_parsed, remaining_string) 
    """ 
    decoder = simplejson.JSONDecoder() 
    obj, end = decoder.raw_decode(s) 
    end = WHITESPACE.match(s, end).end() 
    return obj, s[end:] 

def main(): 
    with open("out.txt") as f: 
     s = f.read() 

    while True: 
     obj, remaining = grabJSON(s) 
     print ">", obj 
     s = remaining 
     if not remaining.strip(): 
      break 

.. che con un po 'simile in JSON out.txt emetterà qualcosa come:

> {'hello': ['world', 'hell', {'test': 'haha'}]} 
> {'hello': ['world', 'hell', {'test': 'haha'}]} 
> {'hello': ['world', 'hell', {'test': 'haha'}]} 
+0

Funziona perfettamente Grazie mille, apprezzo molto. – Rahul

+0

Ho alcuni valori nel dizionario che sono funzioni. per esempio ' {key11: function (argument11) key12: {dict11}} { Key21: function (argument12) key22: {}} dict21 ' E 'possibile estendere il codice per leggere questi dizionari. – Rahul

+0

Puoi dare un esempio più chiaro? Può essere una versione concisa di dati reali. Dal tuo 'key11',' function (argument11) ', è molto difficile distinguere la struttura dei tuoi dati originali - Contiene virgolette? Contiene virgole? Le funzioni devono essere invocate ecc. È necessario modificare la domanda e aggiornare con input e output di esempio. – SuperSaiyan

2

Poiché i dati nel file di input non è davvero in JSON o Python oggetto formato letterale, è Avrai bisogno di analizzarlo da solo. Non hai veramente specificato quali sono le chiavi e i valori ammessi nel dizionario, quindi le seguenti consentono solo di essere stringhe di caratteri alfanumerici.

Quindi, dato un file di input con il seguente contenuto di nome doc.txt:

{key1: value1 
key2: value2 
key3: value3 
} 
{key4: value4 
key5: value5 
} 

Di seguito legge e la trasforma in una lista Python di dizionari composto da chiavi e valori alfanumerici:

from pprint import pprint 
import re 

dictpat = r'\{((?:\s*\w+\s*:\s*\w+\s*)+)\}' # note non-capturing (?:) inner group 
itempat = r'(\s*(\w+)\s*:\s*(\w+)\s*)'  # which is captured in this expr 

with open('doc.txt') as f: 
    lod = [{group[1]:group[2] for group in re.findall(itempat, items)} 
           for items in re.findall(dictpat, f.read())] 

pprint(lod) 

uscita :

[{'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}, 
{'key4': 'value4', 'key5': 'value5'}] 
0
import re 

fl = open('doc.txt', 'rb') 

result = map(
    lambda part: dict(
     re.match(
      r'^\s*(.*?)\s*:\s*(.*?)\s*$', # splits with ':' ignoring space symbols 
      line 
     ).groups() 
     for line in part.strip().split('\n') # splits with '\n', new line is a new key-value 
    ), 
    re.findall(
     r'\{(.*?)\}', # inside of { ... } 
     fl.read(), 
     flags=re.DOTALL # considering '\n'-symbols 
    ) 
) 

fl.close()