2012-12-28 2 views
8

Eventuali duplicati:
Dynamic module import in PythonImporta file utilizzando stringa come nome

ho intenzione di fare una serie di file ad un certo punto presto, e il modo migliore per organizzarlo è di avere una lista, quella lista sarà in cima a un file, e dopo verrà una ridicola quantità di codice per gestire ciò che l'elenco controlla e come funziona. Sto cercando di scrivere tale lista solo una volta, e tale elenco è un elenco di nomi di cartelle e file in questo formato:

[(folder/filename, bool, bool, int), (folder/filename, bool, bool, int)] 

Come si può vedere, folder/filename sono gli stessi (o quasi). Il nome del file è il nome della cartella con .py alla fine, ma con l'importazione XXX non è necessario importare XXX.py, quindi non vedo questo causa di problemi.

Il problema che sto affrontando è l'importazione utilizzando questo metodo ...

for (testName, auto, hardware, bit) in testList: 
    print(testName) 
    paths = "\\" + testName 
    print paths 
    addpath(paths) 
    sys.modules[testName] = testName # One of a few options I've seen suggested on the net 
    print("Path Added") 
    test = testName + ".Helloworld()" 
    eval(test) 

Quindi per ogni test che ho, stampare il nome, assemblare una stringa che contiene il percorso ("\\testName"), per questo esempio , stampare il percorso di test, quindi aggiungere il percorso all'elenco (sys.path.append(path)), quindi stampare per confermare che è successo, quindi assemblare una stringa che verrà eseguita da eval per il modulo principale di test e infine evalificarlo.

Come potete vedere, attualmente sto avendo un elenco di importazioni nella parte superiore. Non posso semplicemente importare testName (il contenuto di testName è il nome del modulo che desidero importare), poiché proverà a trovare un modulo chiamato testName, non un modulo chiamato il contenuto di testName.

Ho visto alcuni esempi di dove è stato fatto, ma non riesco a trovare nessuno che funzioni nelle mie circostanze. Se qualcuno potesse letteralmente buttare un pezzetto di codice che lo farebbe sarebbe meraviglioso.

Avrei anche richiesto che non venissi appeso, disegnato, né squartato per l'uso di eval, esso sia usato in un ambiente molto controllato (l'elenco attraverso il quale si muove all'interno del file .py, quindi no " l'utente finale "dovrebbe scherzare con esso).

+0

Si noti che il rientro è corretto in ST, per qualche ragione, penso che questo sito semplicemente non piace l'analisi mio testo correttamente :( – XtrmJosh

+1

Non utilizzare le schede, ma gli spazi per l'indentazione. –

+2

Python ha già un modo di gestire grandi raccolte di file '.py' che potresti voler importare, che capiscono le cartelle e le sottocartelle, ti permettono di gestire le importazioni relative, il namespaces in modo appropriato e così via. Si chiama un [pacchetto] (http: // docs. python.org/2/tutorial/modules.html#packages). C'è un motivo per cui non vuoi usarne uno? – katrielalex

risposta

24

Non sono sicuro se ho capito tutto correttamente, ma è possibile importare un modulo usando dinamicamente __import__:

mod = __import__(testName) 
mod.HelloWorld() 

Edit: non ero a conoscenza che l'uso di __import__ è stato scoraggiato dai documenti Python per codice utente: __import__ documentation (come notato da Bakuriu)

Questo dovrebbe anche lavorare e sarebbe considerato meglio stile:

mod = importlib.import_module(testName) 
mod.HelloWorld() 
+0

Meraviglioso, grazie mille per questo, ho passato più di un'ora a cercare informazioni su di esso, io è riuscito a scrivere __import __ (testName) in precedenza, ma non si è reso conto che dovevo assegnare la risposta a un modulo o, fortunatamente tutte le mie funzioni saranno denominate Test in tutti i file, quindi posso semplicemente chiamare mod.Test() da ora avanti – XtrmJosh

+0

@XtrmJosh hai visto l'altra risposta? '__import__' è un dettaglio di implementazione; dovresti usare 'importlib' (o' imp' se non ti interessa la compatibilità con Python 3.x). – katrielalex

16
  1. Mai e poi mai pasticciare con sys.modules direttamente se non si sa esattamente cosa si sta facendo.
  2. Ci sono un sacco di modi per fare ciò che si vuole:
    1. La build-in __import__ funzione
    2. Utilizzando imp.load_module
    3. Utilizzando importlib.import_module

Eviterei utilizzando __import__ direttamente, e vai per importlib.import_module (che è anche suggerito alla fine della documentazione di __import__).

+1

Questo è per 'import moduleName' dove moduleName è stringa. Che ne dite di 'from moduleName import *'? –

+2

@NAMGVU prova ad importare il modulo come sopra e poi: 'globals(). Update (module .__ dict __)' – Bakuriu

+0

Funziona come un incantesimo. Grazie! –

0

Aggiungere il percorso in cui il modulo risiede in sys.path. Importa il modulo usando la funzione __import__ che accetta una variabile stringa come nome del modulo.

import sys 
sys.path.insert(0, mypath) # mypath = path of module to be imported 
imported_module = __import__("string_module_name") # __import__ accepts string 
imported_module.myfunction() # All symbols in mymodule are now available normally