Jak zaimportować moduł Python, biorąc pod uwagę jego ścieżkę względną?
Na przykład, jeśli dirFoo
zawiera Foo.py
i dirBar
, i dirBar
zawiera Bar.py
, w jaki sposób mogę zaimportować Bar.py
do Foo.py
?
Oto wizualna reprezentacja:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo
chce dołączyć Bar
, ale restrukturyzacja hierarchii folderów nie wchodzi w grę.
python
relative-path
python-import
Jude Allred
źródło
źródło
Odpowiedzi:
Zakładając, że oba katalogi są prawdziwymi pakietami Pythona (mają w sobie
__init__.py
plik), oto bezpieczne rozwiązanie dla włączenia modułów w zależności od położenia skryptu.Zakładam, że chcesz to zrobić, ponieważ do skryptu musisz dołączyć zestaw modułów. Używam tego w produkcji w kilku produktach i działa w wielu specjalnych scenariuszach, takich jak: skrypty wywoływane z innego katalogu lub uruchamiane za pomocą Python execute zamiast otwierania nowego interpretera.
Jako bonus, takie podejście pozwala zmusić Python do używania twojego modułu zamiast tych zainstalowanych w systemie.
Ostrzeżenie! Naprawdę nie wiem, co się dzieje, gdy bieżący moduł znajduje się w
egg
pliku. Prawdopodobnie też zawodzi.źródło
os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]) + "/subfolder")
Do NOT dodać podfolder przedabspath
jak to powoduje poważne błędy.cmd_subfolder
) bezpośrednio do mojej odpowiedzi. dzięki!realpath
już generuje ścieżki absolutne, więc nie potrzebujęabspath
. Równieżos.path.dirname
może być stosowany zamiast Split, makeing indeksowanie[0]
nieaktualne. Linia byłaby wtedy:os.path.realpath(os.path.dirname(inspect.getfile(inspect.currentframe())))
Upewnij się, że dirBar ma
__init__.py
plik - dzięki temu katalog staje się pakietem Pythona.źródło
sys.path
wtedy obecność__init__.py
wdirBar
katalogu nie pomaga.__init.py__
będzie działać tylko wtedy, gdy katalog jest już w sys.path, aw moim przypadku tak nie było. Rozwiązanie „sorin” (zaakceptowane) zawsze działa.sys.path
zawierał pytania? Być może coś pominięto, o czym nie widzieliśmy?Możesz także dodać podkatalog do ścieżki Pythona, aby importował się jak zwykły skrypt.
źródło
sys.path.append(os.path.dirname(__file__) + "/relative/path/to/module")
sys.path.append(__name__ if __name__ != '__main__' else __loader__.fullname)
sys.path.insert(0, <path to dirFoo>)
ponieważ spowoduje załadowanie tego modułu przed modułami o tej samej nazwie przechowywanymi w innym miejscu.źródło
os.path.join()
zamiast łączenia przez '/', co spowoduje uszkodzenie w (lame) oknach.os.path.abspath(os.path.join(__file__,'..','lib'))
?Po prostu wykonaj proste czynności, aby zaimportować plik .py z innego folderu.
Załóżmy, że masz katalog taki jak:
Następnie po prostu zachowaj pusty plik w folderze lib o nazwie
A potem użyj
Zachowaj
__init__.py
plik w każdym folderze hierarchii modułu importu.źródło
Jeśli skonstruujesz swój projekt w ten sposób:
Następnie z Foo.py powinieneś być w stanie:
Lub:
Zgodnie z komentarzem Toma wymaga to, aby
src
folder był dostępny za pośrednictwemsite_packages
lub ścieżki wyszukiwania. Ponadto, jak wspomina,__init__.py
jest domyślnie importowany podczas pierwszego importu modułu w tym pakiecie / katalogu. Zazwyczaj__init__.py
jest to po prostu pusty plik.źródło
from dirFoo import Foo
powiedziećFoo.bla()
. Jeśli używasz,import dirFoo.Foo
powinieneś użyćdirFoo.Foo.bla()
- dość brzydki, nawet bez futerału na wielbłąda.Najłatwiejszą metodą jest użycie sys.path.append ().
Jednak możesz być także zainteresowany modułem imp . Zapewnia dostęp do wewnętrznych funkcji importu.
Można tego użyć do dynamicznego ładowania modułów, gdy nie znasz nazwy modułu.
Użyłem tego w przeszłości, aby utworzyć interfejs typu wtyczki do aplikacji, w którym użytkownik napisałby skrypt z funkcjami specyficznymi dla aplikacji i po prostu upuściłby swój skrypt w określonym katalogu.
Przydatne mogą być również następujące funkcje:
źródło
To jest odpowiedni PEP:
http://www.python.org/dev/peps/pep-0328/
W szczególności zakładając, że dirFoo jest katalogiem od dirBar ...
W dirFoo \ Foo.py:
źródło
Najłatwiejszym sposobem bez modyfikacji skryptu jest ustawienie zmiennej środowiskowej PYTHONPATH. Ponieważ sys.path jest inicjowany z następujących lokalizacji:
Po prostu biegnij:
Twój sys.path będzie zawierał powyższą ścieżkę, jak pokazano poniżej:
źródło
Moim zdaniem najlepszym wyborem jest umieszczenie __ init __.py w folderze i wywołanie pliku za pomocą
Nie zaleca się używania sys.path.append (), ponieważ coś może pójść nie tak, jeśli użyjesz tej samej nazwy pliku, co istniejący pakiet python. Nie testowałem tego, ale to będzie dwuznaczne.
źródło
from dirBar.Bar import *
działa, ale niefrom dirBar.Bar import Bar
. wiesz dlaczego * działa? co jeśli miałbym wiele plików w dirBar / i chciałbym pobrać tylko kilka z nich (używając metody takiej jak ta, którą tutaj opublikowałeś)?from dirBar import Bar
.from
wskazuje źródło, a wszystko po nimimport
jest, co można pobrać z tego źródła.from dirBar.Bar import Bar
oznacza „Ze źródła zaimportuj samo źródło”, co nie ma sensu. że*
chociaż środki „dać mi wszystko ze źródła”Szybki i brudny sposób dla użytkowników systemu Linux
Jeśli po prostu majstrujesz i nie przejmujesz się problemami z wdrożeniem, możesz użyć dowiązania symbolicznego (zakładając, że twój system plików go obsługuje), aby moduł lub pakiet był bezpośrednio widoczny w folderze żądającego modułu.
lub
Uwaga: „Moduł” to dowolny plik z rozszerzeniem .py, a „pakiet” to dowolny folder zawierający ten plik
__init__.py
(który może być pustym plikiem). Z punktu widzenia użytkowania, moduły i pakiety są identyczne - oba ujawniają zawarte w nich „definicje i instrukcje” zgodnie z żądaniemimport
polecenia.Zobacz: http://docs.python.org/2/tutorial/modules.html
źródło
zamiast:
na wypadek gdyby mógł być zainstalowany inny dirBar i mylić czytnik foo.py.
źródło
Aby zaimportować Bar.py do Foo.py, najpierw zamienię te foldery w pakiety Pythona w następujący sposób:
Następnie zrobiłbym to tak w Foo.py:
Gdybym chciał, aby przestrzeń nazw wyglądała jak Bar. cokolwiek lub
Gdybym chciał przestrzeni nazw dirBar.Bar. cokolwiek . Ten drugi przypadek jest przydatny, jeśli masz więcej modułów w pakiecie dirBar.
źródło
Dodaj plik __init__.py :
Następnie dodaj ten kod na początek Foo.py:
źródło
dirBar
jest już pakietem Python (przez istnieniedirBar/__init__.py
), nie ma potrzeby dołączaniadirBar
do niegosys.path
, nie? Oświadczenieimport Bar
zFoo.py
powinno wystarczyć.Względny przykład sys.path:
Na podstawie tej odpowiedzi.
źródło
Cóż, jak wspomniałeś, zwykle chcesz mieć dostęp do folderu z modułami w stosunku do miejsca uruchamiania skryptu głównego, więc po prostu je zaimportuj.
Rozwiązanie:
Mam skrypt
D:/Books/MyBooks.py
i niektóre moduły (np. Oldies.py). Muszę zaimportować z podkataloguD:/Books/includes
:Umieść
print('done')
woldies.py
, aby sprawdzić, czy wszystko jest w porządku. Ten sposób zawsze działa, ponieważ według definicjisys.path
języka Python zainicjowanej podczas uruchamiania programu, pierwszym elementem tej listypath[0]
, jest katalog zawierający skrypt użyty do wywołania interpretera języka Python.Jeśli katalog skryptów nie jest dostępny (np. Jeśli interpreter jest wywoływany interaktywnie lub jeśli skrypt jest odczytywany ze standardowego wejścia),
path[0]
to pusty ciąg, który kieruje Python najpierw do wyszukiwania modułów w bieżącym katalogu. Zauważ, że katalog skryptów jest wstawiany przed wpisami wstawionymi w wynikuPYTHONPATH
.źródło
site.addsitedir(sys.path[0]+'/includes')
) W moim pierwszym prostym programie Pythona break_time.py: https://github.com/ltfschoen/PythonTest . Używam systemu: MacOS v10.11.5, Python 2.7.12, IDLE IDE 2.7.12, Tk 8.5.9Po prostu możesz użyć:
from Desktop.filename import something
Przykład:
kod:
Ale upewnij się, że utworzyłeś pusty plik o nazwie „
__init__.py
” w tym kataloguźródło
import something
a potem powiedziałem, aby ułatwić*
zasadniczo nie jest to dobre dlaInnym rozwiązaniem byłoby zainstalowanie pakietu Py-Require , a następnie skorzystanie z następujących poleceń
Foo.py
źródło
require()
funkcji, możesz rzucić okiem na mój projekt Node.pyOto sposób na zaimportowanie pliku z jednego poziomu powyżej przy użyciu ścieżki względnej.
Zasadniczo wystarczy przenieść katalog roboczy na wyższy poziom (lub dowolną lokalizację względną), dodać go do ścieżki, a następnie przenieść katalog roboczy z powrotem do miejsca, w którym się zaczął.
źródło
Nie mam doświadczenia w pythonie, więc jeśli w moich słowach jest coś złego, po prostu powiedz mi. Jeśli hierarchia plików ułożona jest w następujący sposób:
module_1.py
definiuje funkcję o nazwiefunc_1()
, module_2.py :i uruchomisz
python module_2.py
w cmd, wykona to, cofunc_1()
definiuje. Tak zazwyczaj importujemy te same pliki hierarchii. Ale kiedy piszeszfrom .module_1 import func_1
wmodule_2.py
, interpreter Pythona powieNo module named '__main__.module_1'; '__main__' is not a package
. Aby to naprawić, po prostu zachowujemy zmiany, które właśnie wprowadzamy, i przenosimy oba moduły do pakietu, i uruchamiamy trzeci moduł jako program wywołującymodule_2.py
.main.py :
Ale powodem dodamy
.
zanimmodule_1
wmodule_2.py
to, że jeśli nie zrobimy tego i runmain.py
, interpreter Pythona powieNo module named 'module_1'
, że to trochę skomplikowane,module_1.py
jest tuż obokmodule_2.py
. Teraz niechfunc_1()
sięmodule_1.py
coś zrobić:który
__name__
rejestruje, kto dzwoni do func_1. Teraz trzymamy.
przedmodule_1
, uruchommain.py
, wydrukujepackage_1.module_1
, a niemodule_1
. Wskazuje, że ten, kto dzwoni,func_1()
jest w tej samej hierarchiimain.py
, co.
implikuje, żemodule_1
jest w tej samej hierarchii co onmodule_2.py
sam. Więc jeśli nie ma kropki,main.py
rozpoznamodule_1
w tej samej hierarchii co ona, może rozpoznaćpackage_1
, ale nie to, co „pod” nią.Teraz zróbmy to trochę skomplikowanym. Masz a
config.ini
i moduł definiuje funkcję do odczytu w tej samej hierarchii co 'main.py'.I z jakiegoś nieuniknionego powodu musisz do niego zadzwonić
module_2.py
, więc musi zostać zaimportowany z wyższej hierarchii. moduł_2.py :Dwie kropki oznaczają import z górnej hierarchii (trzy kropki mają dostęp do górnej niż górnej itd.). Teraz możemy uruchomić
main.py
interpreter powie:ValueError:attempted relative import beyond top-level package
. „Pakiet najwyższego poziomu” tutajmain.py
. Tylko dlatego , żeconfig.py
jest obokmain.py
, są oni w tej samej hierarchii,config.py
nie jest „pod”main.py
lub nie jest „prowadzony” przezmain.py
, więc jest pozamain.py
. Aby to naprawić, najprostszym sposobem jest:Myślę, że jest to zbieżne z zasadą hierarchii plików projektu, powinieneś rozmieścić moduły z różnymi funkcjami w różnych folderach i po prostu zostawić górnego rozmówcę na zewnątrz, i możesz importować, jak tylko chcesz.
źródło
Działa to również i jest znacznie prostsze niż cokolwiek z
sys
modułem:źródło
Zadzwoń do mnie zbyt ostrożnie, ale lubię, aby moje były bardziej przenośne, ponieważ nie jest bezpiecznie zakładać, że pliki zawsze będą w tym samym miejscu na każdym komputerze. Osobiście mam kod najpierw wyszukaj ścieżkę do pliku. Używam Linuksa, więc mój wyglądałby tak:
Oczywiście, o ile nie planujesz spakować ich razem. Ale w takim przypadku tak naprawdę nie potrzebujesz dwóch osobnych plików.
źródło