Jak mogę załadować moduł Python, mając pełną ścieżkę? Pamiętaj, że plik może znajdować się w dowolnym miejscu w systemie plików, ponieważ jest to opcja konfiguracji.
1139
Jak mogę załadować moduł Python, mając pełną ścieżkę? Pamiętaj, że plik może znajdować się w dowolnym miejscu w systemie plików, ponieważ jest to opcja konfiguracji.
Odpowiedzi:
W przypadku języka Python 3.5+:
W przypadku Python 3.3 i 3.4 użyj:
(Chociaż zostało to przestarzałe w Pythonie 3.4.)
W przypadku Python 2 użyj:
Istnieją równoważne funkcje wygody dla skompilowanych plików i bibliotek DLL Pythona.
Zobacz także http://bugs.python.org/issue21436 .
źródło
__import__
.imp.load_source
ustawia tylko.__name__
wartość zwracanego modułu. nie wpływa na ładowanie.imp.load_source()
określa klucz nowego wpisu utworzonego wsys.modules
słowniku, więc pierwszy argument rzeczywiście wpływa na ładowanie.imp
Moduł jest nieaktualna od wersji 3.4:imp
Pakiet czeka Wycofanie na korzyśćimportlib
.Zaletą dodania ścieżki do sys.path (w porównaniu z impem) jest to, że upraszcza to rzeczy podczas importowania więcej niż jednego modułu z jednego pakietu. Na przykład:
źródło
sys.path.append
do wskazywania pojedynczego pliku python zamiast katalogu?importlib.import_module(mod_name)
może być użyty zamiast jawnego importu tutaj, jeśli nazwa modułu nie jest znana w czasie wykonywania, dodałbym jednaksys.path.pop()
na końcu, zakładając, że importowany kod nie próbuje zaimportować większej liczby modułów, ponieważ jest używany.Jeśli moduł najwyższego poziomu nie jest plikiem, ale jest spakowany jako katalog z __init__.py, wówczas zaakceptowane rozwiązanie prawie działa, ale nie całkiem. W Python 3.5+ potrzebny jest następujący kod (zwróć uwagę na dodany wiersz rozpoczynający się od „sys.modules”):
Bez tego wiersza, gdy wykonywany jest moduł exec_module, próbuje on powiązać import względny z twojego najwyższego poziomu __init__.py z nazwą modułu najwyższego poziomu - w tym przypadku „mymodule”. Ale „mymoduł” nie jest jeszcze załadowany, więc pojawi się błąd „SystemError: Moduł macierzysty„ mymoduł ”nie został załadowany, nie może wykonać importu względnego”. Musisz więc powiązać nazwę przed załadowaniem. Powodem tego jest podstawowy niezmiennik względnego systemu importu: „Niezmiennym wstrzymaniem jest to, że jeśli masz sys.modules ['spam'] i sys.modules ['spam.foo'] (tak jak po powyższym imporcie ), ten drugi musi występować jako atrybut foo pierwszego ”, jak omówiono tutaj .
źródło
mymodule
?/path/to/your/module/
jest właściwie/path/to/your/PACKAGE/
? amymodule
masz na myślimyfile.py
?Aby zaimportować moduł, musisz dodać jego katalog do zmiennej środowiskowej, tymczasowo lub na stałe.
Tymczasowo
Na stałe
Dodanie następującego wiersza do
.bashrc
pliku (w systemie Linux) i wykonaniesource ~/.bashrc
w terminalu:Źródło / Źródło: saarrrr , kolejne pytanie dotyczące wymiany stosów
źródło
Wygląda na to, że nie chcesz specjalnie importować pliku konfiguracyjnego (który ma wiele skutków ubocznych i dodatkowych komplikacji), po prostu chcesz go uruchomić i mieć dostęp do wynikowej przestrzeni nazw. Biblioteka standardowa udostępnia interfejs API specjalnie w tym celu w postaci runpy.run_path :
Ten interfejs jest dostępny w Python 2.7 i Python 3.2+
źródło
result[name]
,result.get('name', default_value)
itp)from runpy import run_path; from argparse import Namespace; mod = Namespace(**run_path('path/to/file.py'))
Możesz także zrobić coś takiego i dodać katalog, w którym znajduje się plik konfiguracyjny, do ścieżki ładowania Pythona, a następnie po prostu wykonać normalny import, zakładając, że znasz wcześniej nazwę pliku, w tym przypadku „config”.
Bałagan, ale działa.
źródło
Możesz użyć
metoda z modułu imp .
źródło
imp.load_dynamic(module_name, path_to_file)
dla bibliotek DLLźródło
except:
klauzuli catch-all rzadko jest dobrym pomysłem.save_cwd = os.getcwd()
try: …
finally: os.chdir(save_cwd)
this is already addressed by the standard library
tak, ale python ma nieprzyjemny zwyczaj nie być kompatybilny wstecz ... ponieważ sprawdzona odpowiedź mówi, że istnieją 2 różne sposoby przed i po 3.3. W takim przypadku wolałbym napisać własną funkcję uniwersalną niż sprawdzić wersję w locie. I tak, może ten kod nie jest zbyt dobrze chroniony przed błędami, ale pokazuje pomysł (którym jest os.chdir (), o czym nie myślałem), na podstawie którego mogę napisać lepszy kod. Stąd +1.Oto kod, który działa we wszystkich wersjach Pythona, od 2.7-3.5 i prawdopodobnie nawet w innych.
Przetestowałem to. Może to być brzydkie, ale jak dotąd jest to jedyny, który działa we wszystkich wersjach.
źródło
load_source
nie, ponieważ importuje skrypt i zapewnia skryptowi dostęp do modułów i globałów podczas importowania.Wymyśliłem nieco zmodyfikowaną wersję cudownej odpowiedzi @ SebastianRittau (myślę, że dla Pythona> 3.4), która pozwoli ci załadować plik z dowolnym rozszerzeniem jako moduł używający
spec_from_loader
zamiastspec_from_file_location
:Zaletą jawnego kodowania ścieżki jest
SourceFileLoader
to, że maszyneria nie będzie próbowała ustalić typu pliku z rozszerzenia. Oznacza to, że.txt
za pomocą tej metody można załadować plik podobny do pliku, ale nie można tego zrobićspec_from_file_location
bez określenia modułu ładującego, ponieważ.txt
nie ma go w kataloguimportlib.machinery.SOURCE_SUFFIXES
.źródło
Masz na myśli ładowanie czy importowanie?
Możesz manipulować
sys.path
listą, określić ścieżkę do modułu, a następnie zaimportować moduł. Na przykład, biorąc pod uwagę moduł w:Mógłbyś:
źródło
sys.path[0:0] = ['/foo']
Explicit is better than implicit.
Dlaczego więc niesys.path.insert(0, ...)
zamiastsys.path[0:0]
?Wierzę, że możesz użyć
imp.find_module()
iimp.load_module()
załadować określony moduł. Musisz podzielić nazwę modułu ze ścieżki, tzn. Jeśli chcesz załadować/home/mypath/mymodule.py
, musisz:... ale to powinno załatwić sprawę.
źródło
Możesz użyć
pkgutil
modułu (w szczególnościwalk_packages
metody), aby uzyskać listę pakietów w bieżącym katalogu. Stamtąd użycieimportlib
maszyny do importowania wymaganych modułów jest banalne :źródło
Utwórz moduł python test.py
Utwórz moduł python test_check.py
Możemy zaimportować zaimportowany moduł z modułu.
źródło
Ten obszar Pythona 3.4 wydaje się niezwykle trudny do zrozumienia! Jednak przy odrobinie hakowania przy użyciu kodu Chrisa Calloway'a na początku udało mi się coś załatwić. Oto podstawowa funkcja.
Wygląda na to, że korzysta z nieaktualnych modułów z Python 3.4. Nie udaję, że rozumiem dlaczego, ale wydaje się, że działa z poziomu programu. Odkryłem, że rozwiązanie Chrisa działało w wierszu poleceń, ale nie w programie.
źródło
Nie twierdzę, że jest lepiej, ale ze względu na kompletność chciałem zasugerować
exec
funkcję, dostępną zarówno w Pythonie 2, jak i 3.exec
pozwala na wykonanie dowolnego kodu w zakresie globalnym lub wewnętrznym, dostarczone jako słownik.Na przykład, jeśli masz moduł zapisany w
"/path/to/module
„z funkcją”foo()
, możesz go uruchomić, wykonując następujące czynności:To sprawia, że jest nieco bardziej wyraźne, że ładujesz kod dynamicznie i daje ci dodatkową moc, taką jak możliwość dostarczania niestandardowych wbudowanych funkcji.
A jeśli dostęp za pośrednictwem atrybutów, zamiast kluczy jest dla Ciebie ważny, możesz zaprojektować niestandardową klasę dict dla globałów, która zapewnia taki dostęp, np .:
źródło
Aby zaimportować moduł z podanej nazwy pliku, możesz tymczasowo rozszerzyć ścieżkę i przywrócić ścieżkę systemową w odwołaniu do bloku na końcu :
źródło
To powinno działać
źródło
name, ext = os.path.splitext(os.path.basename(infile))
. Ta metoda działa, ponieważ poprzednie ograniczenie rozszerzenia .py. Powinieneś również prawdopodobnie zaimportować moduł do jakiegoś wpisu zmiennej / słownika.Jeśli mamy skrypty w tym samym projekcie, ale w innym katalogu, możemy rozwiązać ten problem, stosując następującą metodę.
W tej sytuacji
utils.py
jestsrc/main/util/
źródło
Zrobiłem
imp
dla ciebie pakiet . Nazywam toimport_file
i tak to się używa:Możesz go uzyskać na:
http://pypi.python.org/pypi/import_file
lub o
http://code.google.com/p/import-file/
źródło
Importuj moduły pakietów w czasie wykonywania (przepis na Python)
http://code.activestate.com/recipes/223972/
źródło
W Linuksie działa dodawanie dowiązania symbolicznego do katalogu, w którym znajduje się skrypt Pythona.
to znaczy:
Python utworzy
/absolute/path/to/script/module.pyc
i zaktualizuje go, jeśli zmienisz zawartość/absolute/path/to/module/module.py
następnie dołącz następujące w mypythonscript.py
źródło
git
i sprawdzając,git status
czy twoje zmiany w skrypcie faktycznie powodują powrót do dokumentu źródłowego i nie gubią się w eterze.Napisałem własną globalną i przenośną funkcję importu opartą na
importlib
module dla:sys.path
lub od kiedykolwiek przechowywanej ścieżki wyszukiwania.Struktura katalogu przykładów:
Zależność i porządek włączenia:
Realizacja:
Sklep z najnowszymi zmianami: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/python/tacklelib/tacklelib.py
test.py :
testlib.py :
testlib.std1.py :
testlib.std2.py :
testlib.std3.py :
Wyjście (
3.7.4
):Testowany w Pythonie
3.7.4
,3.2.5
,2.7.16
Plusy :
testlib.std.py
astestlib
,testlib.blabla.py
astestlib_blabla
i tak dalej).sys.path
ani miejsca przechowywania ścieżki wyszukiwania.SOURCE_FILE
iSOURCE_DIR
między wywołaniamitkl_import_module
.3.4.x
i wyżej] Czy wymieszać nazw modułu w zagnieżdżonychtkl_import_module
połączeń (ex:named->local->named
albolocal->named->local
i tak dalej).3.4.x
i wyżej] Może automatycznie eksportować zmienne globalne / funkcje / klasy, skąd są zadeklarowane do wszystkich modułów potomnych importowanych przeztkl_import_module
(poprzeztkl_declare_global
funkcję).Wady :
3.3.x
i niższych] Wymagaj deklarowaniatkl_import_module
we wszystkich modułach, które wywołujątkl_import_module
(duplikacja kodu)Aktualizacja 1,2 (tylko dla wersji
3.4.x
wyższej i wyższej):W Pythonie 3.4 i nowszych można ominąć wymóg deklarowania
tkl_import_module
w każdym module przez deklaracjętkl_import_module
w module najwyższego poziomu, a funkcja wstrzykiwałaby się do wszystkich modułów potomnych w jednym wywołaniu (jest to rodzaj importu samodzielnego wdrażania).Aktualizacja 3 :
Dodano funkcję
tkl_source_module
analogową do bashsource
z ochroną wykonania wsparcia podczas importu (zaimplementowano poprzez scalenie modułu zamiast importu).Aktualizacja 4 :
Dodano funkcję
tkl_declare_global
automatycznego eksportowania globalnej zmiennej modułowej do wszystkich modułów potomnych, w których globalna zmienna modułowa nie jest widoczna, ponieważ nie jest częścią modułu potomnego.Aktualizacja 5 :
Wszystkie funkcje zostały przeniesione do biblioteki tacklelib, patrz link powyżej.
źródło
Jest pakiet dedykowany do tego w szczególności:
Jest testowany we wszystkich wersjach Pythona (również Jython i PyPy), ale może być nadmierną umiejętnością w zależności od wielkości projektu.
źródło
Dodanie tego do listy odpowiedzi, ponieważ nie mogłem znaleźć niczego, co działałoby. Umożliwi to import skompilowanych (pyd) modułów python w 3.4:
źródło
dość prosty sposób: załóżmy, że chcesz zaimportować plik ze ścieżką względną ../../MyLibs/pyfunc.py
Ale jeśli zdołasz przejść bez osłony, możesz w końcu uzyskać bardzo długą ścieżkę
źródło
Proste rozwiązanie wykorzystujące
importlib
zamiastimp
pakietu (przetestowane dla Python 2.7, chociaż powinno również działać dla Python 3):Teraz możesz bezpośrednio korzystać z przestrzeni nazw importowanego modułu, w następujący sposób:
Zaletą tego rozwiązania jest to , że nie musimy nawet znać rzeczywistej nazwy modułu, który chcielibyśmy zaimportować , aby użyć go w naszym kodzie. Jest to przydatne, np. W przypadku, gdy ścieżka modułu jest argumentem konfigurowalnym.
źródło
sys.path
, który nie pasuje do każdego przypadku użycia.sys.path.pop()
Ta odpowiedź stanowi uzupełnienie odpowiedzi Sebastiana Rittau na komentarz: „ale co, jeśli nie masz nazwy modułu?” Jest to szybki i nieprzyzwoity sposób na uzyskanie prawdopodobnej nazwy modułu Pythona podając nazwę pliku - po prostu idzie w górę drzewa, dopóki nie znajdzie katalogu bez
__init__.py
pliku, a następnie zamienia go z powrotem w nazwę pliku. W przypadku Python 3.4+ (używa pathlib), co ma sens, ponieważ ludzie Py2 mogą używać „imp” lub innych sposobów importowania względnego:Z pewnością istnieją możliwości ulepszenia, a opcjonalne
__init__.py
pliki mogą wymagać innych zmian, ale jeśli tak__init__.py
, to załatwia sprawę.źródło
Myślę, że najlepszym sposobem jest oficjalna dokumentacja ( 29.1. Imp - Dostęp do wewnętrznych elementów importu ):
źródło