Je veux importer un paquet en fonction de la valeur choisie par l'utilisateur.
La valeur par défaut est file1.py
:
from files import file1
Si l'utilisateur choisit file2
, ça devrait être :
from files import file2
En PHP, je peux le faire en utilisant variables variables :
$file_name = 'file1';
include($$file_name);
$file_name = 'file2';
include($$file_name);
Comment puis-je faire cela en Python?
Python n'a pas de fonctionnalité directement équivalente aux "variables variables" de PHP. Pour obtenir la valeur d'une "variable variable" (ou la valeur de toute autre expression), vous pouvez utiliser la fonction eval
.
foo = "Hello World"
print eval("foo")
Cependant, cela ne peut pas être utilisé dans une instruction import
.
Il est possible d'utiliser le __import__
fonction à importer à l'aide d'une variable.
package = "os"
name = "path"
imported = getattr(__import__(package, fromlist=[name]), name)
est équivalent à
from os import path as imported
Vieux fil, mais j'avais besoin de la réponse, donc quelqu'un d'autre pourrait encore ...
Il existe une façon plus propre de le faire dans Python 2.7+:
import importlib
my_module = importlib.import_module("package.path.%s" % module_name)
Comme Fredrik Lundh déclare:
Quoi qu'il en soit, voici comment fonctionnent ces instructions et fonctions:
import X
Importe le module X et crée une référence à ce module dans l'espace de noms courant. En d'autres termes, après avoir exécuté cette instruction, vous pouvez utiliserX.name
Pour faire référence aux éléments définis dans le module X.
from X import *
Importe le module X et crée des références dans l'espace de noms courant à tous les objets publics définis par ce module (c'est-à-dire tout ce qui n'a pas de nom commençant par "_"). Ou en d'autres termes, après avoir exécuté cette instruction, vous pouvez simplement utiliser un nom simple pour faire référence aux éléments définis dans le module X. Mais X lui-même n'est pas défini, doncX.name
Ne fonctionne pas. Et si le nom était déjà défini, il est remplacé par la nouvelle version. Et si le nom en X est changé pour pointer vers un autre objet, votre module ne le remarquera pas.
from X import a, b, c
Importe le module X et crée des références dans l'espace de noms courant aux objets donnés. Autrement dit, vous pouvez maintenant utilisera
etb
etc
dans votre programme.Enfin,
X = __import__(‘X’)
fonctionne commeimport X
, À la différence près que 1) vous passez le nom du module sous forme de chaîne et 2) l'affectez explicitement à un variable dans votre espace de noms actuel.
Et d'ailleurs, c'est la dernière méthode qui vous intéresse.
Écrivez simplement (par exemple):
var = "datetime"
module = __import__(var)
C'est probablement une très mauvaise idée de laisser l'utilisateur choisir quoi importer. Les packages peuvent exécuter du code lors de l'importation, vous autorisez donc efficacement un utilisateur à exécuter arbitrairement du code sur votre système! Beaucoup plus sûr de faire quelque chose comme
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"
En me basant sur la réponse de mattjbray
:
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.")
Enregistre quelques lignes de code et vous permet de définir safe_names
par programme, ou chargez plusieurs modules et affectez-les à un dict, par exemple.