2013-03-13 20 views
7

ho diversi moduli diversi, e ho bisogno di importare uno di loro a seconda delle situazioni diverse, ad esempio:Come importare selettivamente il modulo in python?

if check_situation() == 1: 
    import helper_1 as helper 
elif check_situation() == 2: 
    import helper_2 as helper 
elif ... 
    ... 
else: 
    import helper_0 as helper 

questi aiutanti contengono dizionari stessi dict01, dict02, dict03 ... ma avere valori diversi per essere chiamato in diverse situazioni.

Ma questo ha qualche problema:

  1. frasi di importazione sono tutti scritti nella parte superiore di un file, ma check_situation() funzione qui ha bisogno di prerequisiti in modo che sia ormai lontano dalla cima.
  2. più di un file ha bisogno di questo modulo di supporto, quindi è difficile e brutto usare questo tipo di importazione.

Quindi, come riorganizzare questi aiutanti?

risposta

1

Risolvere io stesso, riferito a @ Michael Scott Cuthbert

# re_direct.py 

import this_module 
import that_module 

wanted = None 


# caller.py 
import re-direct 

''' 
many prerequisites 
''' 
def imp_now(case): 
    import re_direct 
    if case1: 
     re_direct.wanted = re_direct.this_module 
    elif case2: 
     re_direct.wanted = re_direct.that_module 

quindi, se in chiamante, chiamo quell'imp_now, th it voleva, non importa chiamato nel file del chiamante o in un altro file che chiama questo voluto, verrà reindirizzato a this_or_that_module.

anche, per importare re_direct solo in una funzione, quindi non vedrai questo modulo da nessun'altra parte, ma vedrai solo voluto.

+0

Si noti che questo caricherà il codice per TUTTI i moduli. –

+0

Si noti inoltre che una volta importato 'voluto' non è possibile cambiarlo assegnandogli da' re_direct.wanted'. Qui il reindirizzamento delle importazioni è assolutamente superfluo. –

+0

@DavideR. sì, lo trovo ancora non funziona bene. Non mi interessa caricare tutti i moduli o non può più cambiare. Quindi, come posso fare per far sì che tutti i chiamanti importino this_module o that_module? – ThunderEX

4

Si può usare __import__(), che accetta una stringa e restituisce quel modulo:

helper=__import__("helper_{0}".format(check_situation())) 

esempio:

In [10]: mod=__import__("{0}math".format(raw_input("enter 'c' or '': "))) 
enter 'c' or '': c    #imports cmath 

In [11]: mod.__file__ 
Out[11]: '/usr/local/lib/python2.7/lib-dynload/cmath.so' 

In [12]: mod=__import__("{0}math".format(raw_input("enter 'c' or '': "))) 
enter 'c' or '': 

In [13]: mod.__file__ 
Out[13]: '/usr/local/lib/python2.7/lib-dynload/math.so' 

Come sottolineato da @wim e dai documenti python3.x su __import__():

Importare un modulo. Poiché questa funzione è pensata per essere utilizzata dall'interprete Python e non per uso generale, è preferibile utilizzare importlib.import_module() per importare un modulo a livello di programmazione.

+2

-1 perché leggere il docstring di '__import__' - _ "questa funzione è pensato per l'utilizzo da parte del Python interprete e non per uso generale, è meglio usare importlib.import_module() per importare un modulo di programmazione" _ – wim

+0

inoltre, hai ignorato il "problema dietro il problema", ovvero che l'OP utilizza i dati nei loro nomi variabili – wim

+0

@wim Non riesco a trovare la stessa cosa nella docstring o nei documenti, dal documenti: * Questa funzione è invocata dall'istruzione import. L'uso diretto di __import __() è raro, tranne nei casi in cui si desidera importare un modulo il cui nome è noto solo al runtime. * –

3

In primo luogo, non vi è alcun requisito rigoroso che le istruzioni di importazione debbano essere nella parte superiore di un file, è più una cosa di guida di stile.

Ora, importlib e dict può essere utilizzato per sostituire la catena if/elif:

import importlib 

d = {1: 'helper_1', 2: 'helper_2'} 
helper = importlib.import_module(d.get(check_situation(), 'helper_0')) 

ma è solo zucchero sintattico davvero, ho il sospetto che hai pesci più grandi da friggere. Sembra che tu debba riconsiderare le tue strutture dati e riprogettare il codice.

Ogni volta che si dispone di variabili denominate come dict01, dict02, dict03 è un segno sicuro che è necessario attrezzarsi un livello, e avere qualche contenitore di dicts esempio una lista di loro. Lo stesso vale per i nomi dei moduli 'helper' che terminano con le cifre.

+0

sì Penso che sia davvero necessario riprogettazione. come script originale, se import posso usare helper.dictA, helper.dictB senza sapere quale helper è stato usato. Come ottenere questo effetto? – ThunderEX

+0

Si potrebbero aliasarli nei moduli, ad esempio 'my_dict = dictA' in un modulo helper e' my_dict = dictB' nell'altro. Quindi accedi con 'helper.my_dict'. Ma devo sottolineare che questo risolve un problema tecnico, non un problema di progettazione. – wim

1

Sono d'accordo sul fatto che gli approcci dati nelle altre risposte sono più vicini alla domanda principale posta nel titolo, ma se il sovraccarico sull'importazione dei moduli è basso (come probabilmente un paio di dizionari è probabile) e non ci sono effetti per l'importazione, in questo caso, si può essere meglio di loro tutto l'importazione e la selezione del dizionario corretto più tardi nei moduli:

import helper_0 
import helper_1 
... 
helperList = [helper_0, helper_1, helper_2...] 
... 
helper = helperList[check_situation()] 
Problemi correlati