2012-02-16 42 views
17

Me gustaría crear un diccionario a partir de un archivo de texto que tengo, cuyos contenidos están en formato 'diccionario'. He aquí una muestra de lo que el archivo contiene:Python: Crear Diccionario de Texto/Archivo que está en formato de diccionario

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

Es exactamente esto, excepto que contiene 125,000 entradas. Soy capaz de leer en el archivo de texto usando lectura(), pero crea una variable del texto literal del archivo incluso cuando inicializar la variable con

dict = {}

+8

'ast.literal_eval' – JBernardo

+1

@JBernardo 1 como Mientras tenga Python 2.6 o más reciente, ese es el camino a seguir. El módulo 'ast' se introdujo en 2.5, pero no tenía las funciones auxiliares (como' literal_eval'). Esos llegaron en 2.6. –

+0

@JBernardo, la mejor respuesta – dzhioev

Respuesta

23

Puede utilizar el eval incorporado. Por ejemplo, esto funcionaría si cada entrada del diccionario está en una línea diferente:

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 

Alternativamente, si el archivo es sólo un gran diccionario (incluso en varias líneas), se puede hacer esto:

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

Esta es probablemente la manera más simple de hacerlo, pero no es la más segura. Como otros mencionaron en sus respuestas, eval tiene algunos riesgos de seguridad inherentes. La alternativa, como lo menciona JBernardo, es usar ast.literal_eval, que es mucho más seguro que eval, ya que solo evaluará las cadenas que contienen literales. Simplemente puede reemplazar todas las llamadas a eval en los ejemplos anteriores con ast.literal_eval después de importar el módulo ast.

Si está utilizando Python 2.4 no tendrá el módulo ast, y no va a tener with declaraciones. El código se parecerá más a esto:

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

No se olvide de llamar inf.close(). La belleza de las declaraciones with es que lo hacen por usted, incluso si el bloque de código en la declaración with genera una excepción.

+0

¿Qué pasa si es solo una pared de texto? Literalmente es solo una cadena sólida que comienza con {y termina con}. – Jared

+0

Aún debería funcionar si solo hay una línea. – DynamiteReed

+0

Funcionará si solo hay una línea, aunque no funcionará si el diccionario está distribuido en más de una línea. Agregué código adicional para ese caso. –

0

Esto se parece a json para mí. Use el módulo json si es así.

Esto se ve como yaml para mí. Use el pyyaml module si es así. (Según lo sugerido por @jcollado).

No puede usar el módulo json porque es estricto con respecto a su entrada.

+3

No es JSON: utiliza comillas simples en lugar de comillas dobles. –

+0

@NedBatchelder: Sí. No me di cuenta de que el módulo 'json' era estricto sobre su entrada. – Marcin

1

Utilice la función eval.

Por ejemplo,

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

+1 'eval' es definitivamente lo más simple de hacer. El comentario hecho por @JBernardo sobre 'ast.literal_eval' es más seguro, ya que solo permite cadenas, números, tuplas, listas, dictos, booleanos y Ninguno. Solo algo a considerar. – istruble

1

No recomiendo usar eval sin embargo. Puede ocasionar problemas de seguridad si no tiene control total sobre el archivo de entrada. Simplemente importe su diccionario y guárdelos utilizando el módulo json o pickle.

+0

Acepto que eval es un riesgo de seguridad gigante si se usa de forma regular o en el código de producción, I interpretó la pregunta original para ser trato con un código aislado que proviene de una fuente confiable y ya se encuentra en un archivo de texto. Dada esa situación, no hay mucho más que puedas hacer. – DynamiteReed

+0

Está en un archivo estático de una fuente confiable, ¡sí! – Jared

+0

Y no he tenido suerte con los archivos de pickle. Tengo esta misma información en un archivo .pickle, pero parece que no puedo cargarlo de nuevo. Este código se ejecuta en un sistema restringido sin acceso a Internet. – Jared

3

Usar eval puede ser peligroso.Si JSON no funciona, entonces me gustaría recomendar el uso yaml que parece funcionar bien con su ejemplo de entrada:

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

Ah, me gustaría usar esto pero no tengo el módulo y el sistema en el que se está ejecutando el código no tiene acceso a Internet. ¡Gracias de cualquier manera! – Jared

+0

Es posible que desee considerar la instalación desde la fuente de todos modos. De acuerdo con la documentación, debería ser tan fácil como: 'python setup.py install'. – jcollado

1

No es una solución preparada de producción y podría no funcionar bien con un archivo de su tamaño, pero si necesita una forma sencilla y puede anteponer a presentar a

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

continuación, puede cambiarle el nombre a un archivo Python y simplemente importar

from my_file import my_dict 
Cuestiones relacionadas