2012-02-16 45 views
17

Mi piacerebbe creare un dizionario da un file di testo che ho, il cui contenuto è in un formato 'dizionario'. Ecco un esempio di ciò che il file contiene:Python: creare un dizionario da testo/file in formato dizionario

{ 'fulvo': [1], 'Sermersheim': [3], 'Sonji': [2], 'Scheuring': [2]}

È esattamente questo eccetto che contiene 125.000 voci. Sono in grado di leggere nel file di testo utilizzando read(), ma crea una variabile del testo letterale del file anche quando ho inizializzare la variabile con

dict = {}

+8

'ast.literal_eval' – JBernardo

+1

@JBernardo +1 come a patto che tu abbia Python 2.6 o più recente, questa è la strada da percorrere. Il modulo 'ast' è stato introdotto in 2.5, ma non aveva le funzioni di supporto (come' literal_eval'). Quelli sono arrivati ​​in 2.6. –

+0

@JBernardo, risposta migliore – dzhioev

risposta

23

È possibile utilizzare la eval built-in. Ad esempio, questo dovrebbe funzionare se ogni voce del dizionario è su una linea diversa:

dicts_from_file = [] 
with open('myfile.txt','r') as inf: 
    for line in inf: 
     dicts_from_file.append(eval(line))  
# dicts_from_file now contains the dictionaries created from the text file 

In alternativa, se il file è solo un grande dizionario (anche su più righe), si può fare questo:

with open('myfile.txt','r') as inf: 
    dict_from_file = eval(inf.read()) 

Questo è probabilmente il modo più semplice per farlo, ma non è il più sicuro. Come altri hanno menzionato nelle loro risposte, eval ha alcuni rischi intrinseci per la sicurezza. L'alternativa, come menzionato da JBernardo, è quella di usare ast.literal_eval che è molto più sicuro di eval dato che valuterà solo le stringhe che contengono letterali. È possibile semplicemente sostituire tutte le chiamate a eval negli esempi precedenti con ast.literal_eval dopo l'importazione del modulo ast.

Se si utilizza Python 2.4 non si avrà il modulo ast e non si avranno le istruzioni with. Il codice sarà più simile a questo:

inf = open('myfile.txt','r') 
dict_from_file = eval(inf.read()) 
inf.close() 

Non dimenticare di chiamare inf.close(). La bellezza delle affermazioni with è che lo fanno per te, anche se il blocco di codice nella dichiarazione with solleva un'eccezione.

+0

E se fosse solo un muro di testo? È letteralmente solo una stringa solida che inizia con {e termina con}. – Jared

+0

Dovrebbe funzionare anche se c'è solo una linea. – DynamiteReed

+0

Funzionerà se c'è una sola linea, anche se non funzionerà se il dizionario è distribuito su più di una linea. Ho aggiunto un codice aggiuntivo per quel caso. –

0

Mi sembra un json. Utilizzare il modulo json in caso affermativo.

Questo mi sembra yaml. Utilizzare lo pyyaml module in caso affermativo. (Come suggerito da @jcollado).

Non è possibile utilizzare il modulo json perché è rigido sul suo input.

+3

Non è JSON: usa virgolette singole anziché virgolette. –

+0

@NedBatchelder: Sì. Non mi rendevo conto che il modulo 'json' era rigido sul suo input. – Marcin

1

Utilizzare la funzione eval.

Per esempio,

dict = eval(open("yourfile.txt").read()) 
+0

+1 'eval' è sicuramente la cosa più semplice da fare. Il commento fatto da @JBernardo su 'ast.literal_eval' è più sicuro, in quanto consente solo stringhe, numeri, tuple, liste, dadi, booleani e Nessuno. Solo qualcosa da considerare. – istruble

1

Tuttavia, sconsiglio vivamente di utilizzare eval. Potrebbe causare problemi di sicurezza se non si ha il pieno controllo del file di input. Basta importare il dizionario e salvarli utilizzando il modulo json o pickle.

+0

Sono d'accordo che eval è un rischio per la sicurezza gigante se usato regolarmente o nel codice di produzione, I interpretato la domanda originale da trattare con un bit di codice isolato che proviene da una fonte attendibile e si trova già in un file di testo. Data una tale situazione, non c'è molto altro che puoi fare. – DynamiteReed

+0

Si trova in un file statico da una fonte attendibile, sì! – Jared

+0

E non ho avuto fortuna con i file pickle. Ho le stesse informazioni in un file .pickle, ma non riesco a ricaricarlo. Questo codice viene eseguito su un sistema limitato senza accesso a Internet. – Jared

3

L'utilizzo di eval potrebbe essere pericoloso.Se JSON non funziona, allora mi consiglia di utilizzare yaml che sembra funzionare bene con il tuo esempio di ingresso:

>>> import yaml 
>>> yaml.load("{'fawn': [1], 'sermersheim': [3], 'sonji': [2], 'scheuring': [2]}") 
{'fawn': [1], 'scheuring': [2], 'sermersheim': [3], 'sonji': [2]} 
+0

Ah, mi piacerebbe usarlo ma non ho il modulo e il sistema su cui viene eseguito il codice non ha accesso a Internet. Grazie comunque! – Jared

+0

Si potrebbe comunque prendere in considerazione l'installazione dalla sorgente. Secondo la documentazione, dovrebbe essere facile come: 'python setup.py install'. – jcollado

1

Non è una soluzione pronta di produzione e potrebbe non funzionare bene con un file di vostra dimensione, ma se avete bisogno di un modo semplice e può anteporre si file per

my_dict = {'fawn': [1], 'sermersheim': [3], 'sonji': [2], 'scheuring': [2]} 

allora è possibile rinominare un file python e semplicemente importare

from my_file import my_dict