web-dev-qa-db-fra.com

Comment faire des importations globales à partir d'une fonction?

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()
48
Giovanni Di Milia

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'>
57
Roman Bodnarchuk

Vous pouvez rendre les importations globales dans une fonction comme celle-ci:

def my_imports(module_name):
    globals()[module_name] = __import__(module_name)
9
badzil

Vous pouvez demander à cette fonction de renvoyer les noms des modules que vous souhaitez importer, puis utilisez

mod == __import__(module_name)
2
ChrisB

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
2
maxschlepzig

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"

1
mshaffer

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
1
rafał grabie

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__)
0
Jan