Je crains que ce soit une façon désordonnée d'aborder le problème mais ...
supposons que je souhaite effectuer des importations en Python en fonction de certaines conditions.
Pour cette raison, je veux écrire une fonction:
def conditional_import_modules(test):
if test == 'foo':
import onemodule, anothermodule
Elif test == 'bar':
import thirdmodule, and_another_module
else:
import all_the_other_modules
Maintenant, comment puis-je avoir les modules importés disponibles globalement?
Par exemple:
conditional_import_modules(test='bar')
thirdmodule.myfunction()
Les modules importés ne sont que des variables - des noms liés à certaines valeurs. Il suffit donc de les importer et de les rendre globaux avec le mot clé global
.
Exemple:
>>> math
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'math' is not defined
>>> def f():
... global math
... import math
...
>>> f()
>>> math
<module 'math' from '/usr/local/lib/python2.6/lib-dynload/math.so'>
Vous pouvez rendre les importations globales dans une fonction comme celle-ci:
def my_imports(module_name):
globals()[module_name] = __import__(module_name)
Vous pouvez demander à cette fonction de renvoyer les noms des modules que vous souhaitez importer, puis utilisez
mod == __import__(module_name)
Vous pouvez utiliser la fonction intégrée __import__
pour importer conditionnellement un module avec une étendue globale.
Pour importer un module de niveau supérieur (pensez: import foo
):
def cond_import():
global foo
foo = __import__('foo', globals(), locals())
Importer à partir d'une hiérarchie (pensez: import foo.bar
):
def cond_import():
global foo
foo = __import__('foo.bar', globals(), locals())
Importer à partir d'une hiérarchie et d'un alias (pensez: import foo.bar as bar
):
def cond_import():
global bar
foo = __import__('foo.bar', globals(), locals())
bar = foo.bar
J'aime l'approche @badzil.
def global_imports(modulename,shortname = None, asfunction = False):
if shortname is None:
shortname = modulename
if asfunction is False:
globals()[shortname] = __import__(modulename)
else:
globals()[shortname] = eval(modulename + "." + shortname)
Donc, quelque chose qui est traditionnellement dans un module de classe:
import numpy as np
import rpy2
import rpy2.robjects as robjects
import rpy2.robjects.packages as rpackages
from rpy2.robjects.packages import importr
Peut être transformé en une portée globale:
global_imports("numpy","np")
global_imports("rpy2")
global_imports("rpy2.robjects","robjects")
global_imports("rpy2.robjects.packages","rpackages")
global_imports("rpy2.robjects.packages","importr",True)
Peut avoir quelques bugs, que je vais vérifier et mettre à jour. Le dernier exemple pourrait aussi avoir un alias qui serait un autre "nom court" ou un hack comme "importr | aliasimportr"
Je viens d'avoir le même problème, voici ma solution:
class GlobalImport:
def __enter__(self):
return self
def __call__(self):
import inspect
self.collector = inspect.getargvalues(inspect.getouterframes(inspect.currentframe())[1].frame).locals
def __exit__(self, *args):
globals().update(self.collector)
alors, n'importe où dans le code:
with GlobalImport() as gi:
import os, signal, atexit, threading, _thread
# whatever you want it won't remain local
# if only
gi()
# is called before the end of this block
# there you go: use os, signal, ... from whatever place of the module
J'aime l'approche @ rafał grabie. Comme il prend même en charge l'importation de tous. c'est à dire. depuis os import *
(Bien que ce soit une mauvaise pratique XD)
Non autorisé à commenter, mais voici une version 2.7 de python.
Également supprimé la nécessité d'appeler la fonction à la fin.
class GlobalImport:
def __enter__(self):
return self
def __exit__(self, *args):
import inspect
collector = inspect.getargvalues(inspect.getouterframes(inspect.currentframe())[1][0]).locals
globals().update(collector)
def test():
with GlobalImport() as gi:
## will fire a warning as its bad practice for python.
from os import *
test()
print path.exists(__file__)