2012-12-28 21 views
8

Powiel możliwe:
Dynamic module import in PythonImportuj plik używając ciąg jako nazwa

Zamierzam złożyć zestaw plików w pewnym momencie wkrótce, a najlepszym sposobem, aby zorganizować to mieć lista, ta lista będzie na samym szczycie pliku, a po niej pojawi się śmieszna ilość kodu do obsługi tego, co ta lista kontroluje i jak działa. Szukam napisać wspomnianej listy tylko raz, a że lista jest listą nazw folderów i plików w tym formacie:

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

Jak widać, folder/filename są takie same (w pewnym sensie). Nazwa pliku to nazwa folderu z końcem .py, ale podczas importowania pliku XXX nie trzeba importować pliku XXX.py, więc nie widzę powodującego problemu.

Problem jestem stoi importuje użyciu tej metody ...

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) 

Więc dla każdego testu mam wydrukować nazwę, montaż ciąg, który zawiera ścieżkę ("\\testName"), na tym przykładzie , wydrukuj ścieżkę testową, a następnie dodaj ścieżkę do listy (sys.path.append(path)), a następnie wydrukuj, aby potwierdzić, że to się stało, a następnie zmontuj ciąg znaków, który zostanie wykonany przez eval dla modułu głównego testów i ewentualnie sprawdź go.

Jak widać, obecnie muszę mieć listę importów na górze. Nie mogę po prostu importować testName (zawartość testName to nazwa modułu, który chcę zaimportować), ponieważ spróbuje znaleźć moduł o nazwie testName, a nie moduł o nazwie testName.

Widziałem kilka przykładów tego, gdzie zostało to zrobione, ale nie mogę znaleźć żadnej pracy w moich okolicznościach. Jeśli ktoś mógłby dosłownie rzucić kawałek kodu, który to byłoby wspaniałe.

Prosiłbym również o to, żebym nie był zawieszony, narysowany ani poćwiartowany na użytek eval, jest używany w bardzo kontrolowanym środowisku (lista, przez którą cyklicznie jest w pliku .py, więc nie ma " użytkownik końcowy "powinien się z tym pogodzić).

+0

Zauważ, że wcięcie jest poprawna w ST, z jakiegoś powodu myślę, że ta strona po prostu nie lubi parsowania mój tekst poprawnie :( – XtrmJosh

+1

Nie należy używać kart, ale obowiązuje dla wcięcia. –

+2

Python ma już sposób zarządzania dużymi kolekcjami plików ".py", które możesz zaimportować, które rozpoznają foldery i podfoldery, umożliwiają obsługę importów względnych, poprawne tworzenie przestrzeni nazw itd. Nazywa się to [pakiet] (http: // docs. python.org/2/tutorial/modules.html#packages). Czy istnieje powód, dla którego nie chcesz go używać? – katrielalex

Odpowiedz

24

Nie wiem czy zrozumiałem wszystko poprawnie, ale można zaimportować moduł dynamicznie przy użyciu __import__:

mod = __import__(testName) 
mod.HelloWorld() 

Edit: Nie byłem świadomy, że korzystanie z __import__ zniechęcił przez docs Pythona Kod użytkownika: __import__ documentation (jak zauważył Bakuriu)

powinno to również pracować i będą uważane za lepsze styl:

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

Cudownie, dziękuję za to, spędziłem ponad godzinę, szukając informacji na ten temat. udało mi się wcześniej napisać __import __ (testName), ale nie zdawałem sobie sprawy, że muszę przypisać odpowiedź do modułu lub my, na szczęście wszystkie moje funkcje będą nazywane Testem dla wszystkich plików, więc mogę po prostu wywołać mod.Test() z teraz. – XtrmJosh

+0

@XtrmJosh Czy widziałeś inną odpowiedź? '__import__' jest szczegółem implementacji; powinieneś użyć 'importlib' (lub' imp' jeśli nie zależy Ci na kompatybilności z Pythonem 3.x). – katrielalex

16
  1. Nigdy, przenigdy nie zadzwoń z sys.modules bezpośrednio, jeśli nie wiesz dokładnie, co robisz.
  2. Istnieje wiele sposobów na to, co chcesz:
    1. Nagromadzenie w __import__ funkcja
    2. Korzystanie imp.load_module
    3. Korzystanie importlib.import_module

będę unikać __import__ bezpośrednio, i przejdź do importlib.import_module (co jest również sugerowane na końcu dokumentacji __import__).

+1

Jest to dla 'import nazwa_modelu' gdzie nazwa_modułu jest ciągiem. Co powiesz na 'from moduleName import *'? –

+2

@NamGVU spróbuj zaimportować moduł jak powyżej, a następnie: 'globals(). Update (moduł .__ dict __)' – Bakuriu

+0

Działaj jak czar. Dziękuję Ci! –

0

Dodaj ścieżkę do miejsca, w którym moduł znajduje się w sys.path. Zaimportuj moduł za pomocą funkcji __import__, która przyjmuje zmienną łańcuchową jako nazwę modułu.

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