Chcę dziedziczyć po klasie w pliku znajdującym się w katalogu powyżej bieżącego.
Czy można względnie zaimportować ten plik?
źródło
Chcę dziedziczyć po klasie w pliku znajdującym się w katalogu powyżej bieżącego.
Czy można względnie zaimportować ten plik?
from ..subpkg2 import mod
Zgodnie z dokumentacją w języku Python: w hierarchii pakietów użyj dwóch kropek, jak mówi dokument w instrukcji importu :
Podczas określania modułu do zaimportowania nie trzeba podawać bezwzględnej nazwy modułu. Gdy moduł lub pakiet jest zawarty w innym pakiecie, możliwe jest dokonanie względnego importu w tym samym górnym pakiecie bez konieczności podawania nazwy pakietu. Używając wiodących kropek w określonym module lub pakiecie
from
, możesz określić, jak wysoko przejść w górę bieżącej hierarchii pakietów bez podawania dokładnych nazw. Jedna wiodąca kropka oznacza bieżącą paczkę, w której istnieje moduł dokonujący importu. Dwie kropki oznaczają jeden poziom pakietu . Trzy kropki w górę o dwa poziomy itd. Więc jeśli wykonaszfrom . import mod
z modułu wpkg
pakiecie, zakończysz importowaniepkg.mod
. Jeśli wykonaszfrom ..subpkg2 import mod
od wewnątrzpkg.subpkg1
, zaimportujeszpkg.subpkg2.mod
. Specyfikacja importu względnego zawarta jest w PEP 328 .
PEP 328 dotyczy importu bezwzględnego / względnego.
źródło
Odpowiedź @ gimel jest poprawna, jeśli możesz zagwarantować, że wspomniana hierarchia pakietów. Jeśli nie możesz - jeśli twoja prawdziwa potrzeba jest taka, jak ją wyraziłeś, związana wyłącznie z katalogami i bez żadnego koniecznego związku z pakowaniem - musisz dalej
__file__
szukać katalogu nadrzędnego (wystarczy kilkaos.path.dirname
połączeń; -), a następnie (jeśli ten katalog nie jest jeszcze włączonysys.path
) tymczasowo wstaw ten katalog na samym początkusys.path
,__import__
wyjmij powiedział reż ponownie - niechlujny pracy rzeczywiście, ale „kiedy musisz, musisz” (i Pyhon dąży do nigdy nie powstrzymuj programisty przed zrobieniem tego, co należy zrobić - tak jak mówi norma ISO C w części „Spirit of C” we wstępie! -).Oto przykład, który może Ci pomóc:
źródło
sys.path
dzięki czemu ten sam moduł będzie dostępny pod różnymi nazwami i wszystkimi odpowiadającymi im błędami. autopath.py w pypy lub _preamble.py w twisted rozwiązuj go za pomocą kryteriów wyszukiwania, które identyfikują pakiet najwyższego poziomu, podczas gdy katalogi przechodzą w górę.sys.path.remove(pathYouJustAdded)
po importowaniu, którego potrzebujesz, aby nie zachować tej nowej ścieżki.Zaimportuj moduł z katalogu znajdującego się dokładnie jeden poziom powyżej bieżącego katalogu:
źródło
from .. import module
I dostał błąd ValueError: Podjęto próbę importu względnego w pakiecie , postępując zgodnie z zaleceniemJak załadować moduł będący katalogiem do góry
przedmowa: Dokonałem znacznej przeróbki poprzedniej odpowiedzi z nadzieją, że pomogę wprowadzić ludzi w ekosystem Pythona i mam nadzieję dać wszystkim najlepszą zmianę sukcesu dzięki systemowi importu Pythona.
Obejmuje to względny import w ramach pakietu , co moim zdaniem jest najbardziej prawdopodobnym przypadkiem pytania OP.
Python jest systemem modułowym
Dlatego piszemy,
import foo
aby załadować moduł „foo” z głównej przestrzeni nazw, zamiast pisać:Python nie jest sprzężony z systemem plików
Dlatego możemy osadzić Pythona w środowisku, w którym nie ma systemu plików defacto, bez zapewnienia wirtualnego, takiego jak Jython.
Oddzielony od systemu plików pozwala na elastyczny import, ten projekt pozwala na takie rzeczy jak import z plików archiwalnych / zip, import singletonów, buforowanie kodów bajtowych, rozszerzenia cffi, a nawet zdalne ładowanie definicji kodu.
Więc jeśli importy nie są połączone z systemem plików, co oznacza „jeden katalog w górę”? Musimy wybrać heurystykę, ale możemy to zrobić, na przykład podczas pracy w pakiecie , niektóre heurystyki zostały już zdefiniowane, dzięki czemu import względny jest podobny
.foo
i..foo
działa w ramach tego samego pakietu. Chłodny!Jeśli naprawdę chcesz połączyć wzorce ładowania kodu źródłowego z systemem plików, możesz to zrobić. Będziesz musiał wybrać własną heurystykę i użyć jakiegoś sprzętu importującego, polecam importlib
Przykład importlib Pythona wygląda mniej więcej tak:
Opakowanie
Świetny przykładowy projekt dostępny oficjalnie tutaj: https://github.com/pypa/sampleproject
Pakiet Pythona to zbiór informacji o kodzie źródłowym, który może informować inne narzędzia, jak skopiować kod źródłowy na inne komputery i jak zintegrować kod źródłowy ze ścieżką tego systemu, aby
import foo
działał na innych komputerach (niezależnie od interpretera, system operacyjny hosta itp.)Struktura katalogów
Pozwala mieć nazwę pakietu
foo
w jakimś katalogu (najlepiej w pustym katalogu).Preferuję tworzenie
setup.py
jako rodzeństwofoo.py
, ponieważ upraszcza to pisanie pliku setup.py, jednak możesz napisać konfigurację, aby zmienić / przekierować wszystko, co domyślnie robi setuptools; na przykład umieszczeniefoo.py
w katalogu „src /” jest dość popularne, nie zostało tutaj omówione..
.
„edytowalne” aka
-e
po raz kolejny przekieruje maszynę importującą, aby załadować pliki źródłowe do tego katalogu, zamiast kopiować aktualne dokładne pliki do biblioteki środowiska instalacyjnego. Może to również powodować różnice w zachowaniu na komputerze dewelopera, koniecznie przetestuj swój kod! Są inne narzędzia niż pip, jednak polecam pip być wprowadzający :)Lubię też tworzyć
foo
„pakiet” (katalog zawierający__init__.py
) zamiast modułu (pojedynczy plik „.py”), zarówno „pakiety”, jak i „moduły” mogą być ładowane do głównej przestrzeni nazw, moduły pozwalają na zagnieżdżone przestrzenie nazw, co jest pomocne, jeśli chcemy mieć import „względny jeden katalog do góry”..
Lubię też zrobić a
foo/__main__.py
, to pozwala pythonowi wykonać pakiet jako moduł, np.python3 -m foo
Wykona sięfoo/__main__.py
jako__main__
..
Uzupełnijmy to o kilka modułów: Zasadniczo możesz mieć strukturę katalogów taką jak:
setup.py
konwencjonalnie przechowuje informacje o metadanych o kodzie źródłowym, takie jak:foo
, chociaż popularne jest zastępowanie podkreślników łącznikamipython ./setup.py test
Jest bardzo rozbudowany, może nawet kompilować rozszerzenia c w locie, jeśli moduł źródłowy jest instalowany na maszynie programistycznej. Dla codziennego przykładu polecam setup.py PYPA Sample Repository
Jeśli zwalniasz artefakt kompilacji, np. Kopię kodu, który ma uruchamiać prawie identyczne komputery, plik wymagania.txt jest popularnym sposobem na wykonanie migawki dokładnych informacji o zależnościach, gdzie „install_requires” jest dobrym sposobem na uchwycenie minimum i maksymalnie kompatybilne wersje. Jednak biorąc pod uwagę fakt, że docelowe maszyny i tak są prawie identyczne, bardzo polecam utworzenie tarballa całego prefiksu Pythona. Może to być trudne, zbyt szczegółowe, aby się tutaj dostać. Sprawdź
pip install
„s--target
opcję lub virtualenv aka venv dla potencjalnych klientów.powrót do przykładu
jak zaimportować plik o jeden katalog w górę:
Z foo / spam / eggs.py, gdybyśmy chcieli kodu z foo / baz, moglibyśmy go poprosić o jego absolutną przestrzeń nazw:
Jeśli chcielibyśmy zarezerwować możliwość przeniesienia eggs.py do innego katalogu w przyszłości za pomocą innej względnej
baz
implementacji, moglibyśmy użyć importu względnego, takiego jak:źródło
Python jest systemem modułowym
Python nie polega na systemie plików
Aby niezawodnie ładować kod Pythona, umieść ten kod w module, a moduł ten zainstaluj w bibliotece Pythona.
Zainstalowane moduły zawsze można załadować z przestrzeni nazw najwyższego poziomu za pomocą
import <name>
Świetny przykładowy projekt dostępny jest oficjalnie tutaj: https://github.com/pypa/sampleproject
Zasadniczo możesz mieć taką strukturę katalogów:
.
Pamiętaj, aby zadeklarować
setuptools.setup()
insetup.py
,oficjalny przykład: https://github.com/pypa/sampleproject/blob/master/setup.py
W naszym przypadku prawdopodobnie chcemy wyeksportować,
bar.py
afoo/__init__.py
mój krótki przykład:setup.py
.
Teraz możemy zainstalować nasz moduł w bibliotece Pythona; dzięki pip możesz zainstalować
the_foo_project
w bibliotece Pythona w trybie edycji, abyśmy mogli pracować nad nim w czasie rzeczywistym.
Teraz z dowolnego kontekstu Pythona możemy załadować nasze współdzielone py_modules i pakiety
foo_script.py
źródło
pip install --edit foo
, prawie zawsze wewnątrz virtualenv. Prawie nigdy nie piszę modułu, który nie jest przeznaczony do zainstalowania. jeśli źle zrozumiem coś, co chciałbym wiedzieć.editable
linki do jaj i zainstalowane moduły python nie są dokładnie takie same pod każdym względem; na przykład dodanie nowej przestrzeni nazw do modułu edytowalnego zostanie znalezione podczas wyszukiwania ścieżki, ale jeśli nie zostanie to wyeksportowane do pliku setup.py, nie zostanie spakowane / zainstalowane! Przetestuj swój przypadek użycia :)