2010-09-23 22 views
5

¿Cómo puedo pasar un diccionario a un script de python desde otro script de python sobre la línea de comando? Yo uso el subproceso para llamar al segundo script.Pasar diccionarios a un script de Python a través de la línea de comando

Las opciones que he encontrado son:
I) Construir un módulo para analizar un diccionario a partir de una cadena (más en profundidad de lo que esperaba).
II) Use un archivo temporal para escribir un pickle, y pase el nombre del archivo como argumento
III) No permita diccionarios, pero maneje pares clave/valor (es decir "prog.py keya valuea keyb valub")

La solución no tiene que ser fácil de usar, pero debe ser compatible con los programas. El segundo programa debe ejecutarse como un proceso separado, debido a problemas de seguridad y recursos.

Respuesta

6

Aparte de pickle, otra opción es ast.literal_eval, si sus diccionarios solo contienen primitivos de Python.

>>> d = {3: 9, 'apple': 'orange'} 
>>> s = str(d) 
>>> s 
"{3: 9, 'apple': 'orange'}" 
>>> import ast 
>>> x = ast.literal_eval(s) 
>>> x 
{3: 9, 'apple': 'orange'} 
+0

Esto es exactamente lo que estaba buscando –

6

Si no necesita una estructura de datos demasiado complicada, ¿podría recomendar simplejson? Está disponible como un módulo integrado (llamado json) en Python 2.6 y posterior.

+0

Sí, se puede pasar el diccionario serializado JSON escribiéndolo a la entrada estándar de la segunda guión. – Epeli

+0

+1 porque JSON es simple, efectivo y casi idéntico a la estructura 'dict' de Python. – jathanism

+0

+1 porque es perfecto, aunque la respuesta de FoggleBird es perfecta, y no puedo hablar con el jefe sobre nada que trate con javascript –

8

¿Has mirado el módulo pickle para pasar los datos a través de stdout/stdin?

Ejemplo:

knights.py:

import pickle 
import sys 

desires = {'say': 'ni', 'obtain': 'shrubbery'} 
pickle.dump(desires, sys.stdout) 

roundtable.py:

import pickle 
import sys 

knightsRequest = pickle.load(sys.stdin) 
for req in knightsRequest: 
    print "The knights %s %s." % (req, knightsRequest[req]) 

Uso y salida:

$ python knights.py | python roundtable.py 
The knights say ni. 
The knights obtain shrubbery. 
+0

¡No es una mala idea! – jathanism

0

Sólo imprimir el diccionario en una secuencia de comandos Python

print("dict=" + str(dict)) 

y utilizarlo como

(python script1.py; cat script2.py) | python - 

y ahora usted debería ser capaz de acceder el diccionario través de la variable global 'dict' en el Segundo script de python.

2

Si lo que hay en el diccionario (tanto las claves como los valores) se puede representar como cadenas, debería poder pasarlo como un argumento de cadena al segundo script que puede volver a crearlo.

d = {'a':1,'b':2} 

d == eval(repr(d), None) 

>>>True 

Editar: Aquí está un ejemplo un poco más complicado que muestra su uso con una simple clase personalizada:

class MyClass: 
    def __init__(self, a, b): 
     self.a = a 
     self.b = b 
    def __repr__(self): 
     return 'MyClass(%r, %r)' % (self.a, self.b) 
    def __eq__(self, other): 
     return (self.a == other.a) and (self.b == other.b) 

d = {'foo':42, 'bar': MyClass(17,'astring') } 

print 'd:', d 
print 'repr(d):', repr(d) 
print "d == eval(repr(d), {'MyClass':MyClass})?:", \ 
     d == eval(repr(d), {'MyClass':MyClass}) 

# outputs: 
# d: {'foo': 42, 'bar': MyClass(17, 'astring')} 
# repr(d): {'foo': 42, 'bar': MyClass(17, 'astring')} 
# d == eval(repr(d), {'MyClass':MyClass})?: True 
+0

'ast.literal_eval' es la forma segura y correcta de hacerlo. – FogleBird

+0

'ast.literal_eval()' puede ser demasiado restrictivo. En lugar de None, es posible pasar 'eval()' un segundo argumento que es un mapeo del diccionario de nombres de clase personalizados a las clases personalizadas correspondientes que, cuando se proporcionan, permitirían que las instancias de ellos también se reconstituyan además de las cadenas, números , tuplas, listas, dictados, booleanos y tipos de valores Ninguno que 'ast.literal_eval()' admite. – martineau

Cuestiones relacionadas