2011-07-13 10 views
30

Quiero importar algún paquete dependiendo de qué valor elija el usuario.

El valor predeterminado es file1.py:

from files import file1 

Si el usuario elige file2, que debe ser:

from files import file2 

En PHP, puedo hacer esto utilizando variable variables:

$file_name = 'file1'; 
include($$file_name); 
$file_name = 'file2'; 
include($$file_name); 

¿Cómo puedo hacer esto en Python?

+1

¡No hagas esto! El uso de entrada no suele ser fiable y deslumbrante código de evaluación en función de que es una mala idea. –

+0

gracias, estoy usando el conjunto predeterminado para importar ahora. – skargor

Respuesta

43

Python no tiene una característica que es directamente equivalente a las "variables variables" de PHP. Para obtener el valor de "variable variable" (o el valor de cualquier otra expresión) puede usar la función eval.

foo = "Hello World" 
print eval("foo") 

Sin embargo, esto no se puede utilizar en una sentencia import.

Es posible usar la función __import__ para importar usando una variable.

package = "os" 
name = "path" 

imported = getattr(__import__(package, fromlist=[name]), name) 

es equivalente a

from os import path as imported 
26

Como Fredrik Lundh states:

De todos modos, aquí es cómo funcionan estas declaraciones y funciones:

import X importa el módulo X, y crea una referencia a ese módulo en el espacio de nombres actual. O en otras palabras, después de que haya ejecutado esta declaración , puede utilizar X.name para referirse a cosas definidas en el módulo X.

from X import * importa el módulo X y crea referencias en el espacio de nombres actual a todos los objetos públicas definidas por ese módulo (que es, todo lo que no tiene un nombre que comienza con "_"). O bien, en , después de ejecutar esta instrucción, puede simplemente usar un nombre simple para referirse a cosas definidas en el módulo X. Pero X no está definido en sí mismo, por lo que X.name no funciona. Y si el nombre ya estaba definido, es reemplazado por la nueva versión. Y si el nombre en X se cambia al punto en algún otro objeto, su módulo no lo notará.

from X import a, b, c importa el módulo X y crea referencias en el espacio de nombre actual para los objetos especificados. O en otras palabras, puede ahora usar a y b y c en su programa.

Por último, X = __import__(‘X’) obras como import X, con la diferencia de que 1) Pase el nombre del módulo como una cadena, y 2) asignar explícitamente a una variable en el espacio de nombres actual. .

Y por cierto que es el último método que estás interese

Basta con escribir (por ejemplo):

var = "datetime" 
module = __import__(var) 
+0

Gracias por una respuesta clara y completa. – DrBailey

4

Es probablemente una muy mala idea para permitir al usuario elegir qué importar. Los paquetes pueden ejecutar código en la importación, por lo que efectivamente le permite a un usuario ejecutar código de forma arbitraria en su sistema. Mucho más seguro para hacer algo como

if user_input == 'file1.py': 
    from files import file1 as file 
elif user_input == 'file2.py': 
    from files import file2 as file 
else: 
    file = None 
    print "Sorry, you can't import that file" 
33

hilo viejo, pero necesitaba la respuesta, por lo que otra persona aún podría ...

Hay una forma más limpia de hacer esto en Python 2.7+:

import importlib 


my_module = importlib.import_module("package.path.%s" % module_name) 
+0

Consejo: necesitará un 'package.path .__ init __. Py' para [import to work] (http://stackoverflow.com/a/1260813/673991) en absoluto. –

2

basándome en mattjbray 's respuesta:

from importlib import import_module 

# lookup in a set is in constant time 
safe_names = {"file1.py", "file2.py", "file3.py", ...} 

user_input = ... 

if user_input in safe_names: 
    file = import_module(user_input) 
else: 
    print("Nope, not doing this.") 

países unas pocas líneas de código, y permite puede configurar safe_names mediante programación, o cargar múltiples módulos y asignarlos a un dict, por ejemplo.