Tengo un código en forma de cadena y me gustaría crear un módulo sin escribir en el disco.Cargar módulo de cadena en python
Cuando intento usar IMP y un objeto StringIO hacer esto, me sale:
>>> imp.load_source('my_module', '', StringIO('print "hello world"'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: load_source() argument 3 must be file, not instance
>>> imp.load_module('my_module', StringIO('print "hello world"'), '', ('', '', 0))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: load_module arg#2 should be a file or None
¿Cómo puedo crear el módulo sin tener un archivo real? Alternativamente, ¿cómo puedo envolver un StringIO en un archivo sin escribir en el disco?
ACTUALIZACIÓN:
NOTA: Este problema es también un problema en python3.
El código que intento cargar solo es parcialmente confiable. Lo he probado con ast y he decidido que no importa nada ni hago nada que no me guste, pero no confío lo suficiente como para ejecutarlo cuando tengo variables locales corriendo que podrían modificarse, y No confío en mi propio código para no interferir con el código que intento importar.
creé un módulo vacío que sólo contiene lo siguiente:
def load(code):
# Delete all local variables
globals()['code'] = code
del locals()['code']
# Run the code
exec(globals()['code'])
# Delete any global variables we've added
del globals()['load']
del globals()['code']
# Copy k so we can use it
if 'k' in locals():
globals()['k'] = locals()['k']
del locals()['k']
# Copy the rest of the variables
for k in locals().keys():
globals()[k] = locals()[k]
A continuación, puede importar mymodule
y llame mymodule.load(code)
. Esto funciona para mí porque me he asegurado de que el código que estoy cargando no use globals
. Además, la palabra clave global
es solo una directiva de analizador y no puede hacer referencia a nada que esté fuera del ejecutivo.
Esto realmente es demasiado trabajo para importar el módulo sin escribir en el disco, pero si alguna vez quiere hacerlo, creo que es la mejor manera.
Si usted no confía en el código, no cargarlo. Es terriblemente difícil hacer que un intérprete de Python sea realmente seguro (por ejemplo, hay algunas maneras de parchar el bytecode de un marco de pila diferente una vez que tienes acceso a un objeto de código). Entonces, si esto es solo para evitar errores, podría funcionar, por seguridad, probablemente sea una mala idea. – schlenk
He usado ast bastante extensamente para asegurarme de que no puede hacer nada peligroso. Puede haber agujeros, pero estoy bastante seguro de que los agujeros se pueden reparar si se descubren. –
'del locals() ['code']' no hace nada, ya que el diccionario 'locals()' no es más que un proxy, un reflejo de los lugareños reales. Simplemente use 'del código' si debe eliminar una referencia. No es que esté seguro de por qué estás haciendo esto en absoluto. ¿Por qué todo el baile con 'globals()' y 'locals()' * en primer lugar *? –