Importowanie ze ścieżki względnej w Pythonie


Odpowiedzi:


142

EDYCJA listopad 2014 (3 lata później):

Python 2.6 i 3.x obsługuje prawidłowe importowanie względne, dzięki czemu można uniknąć robienia czegokolwiek hakerskiego. Dzięki tej metodzie wiesz, że otrzymujesz import względny, a nie bezwzględny . „..” oznacza, przejdź do katalogu nad mną:

from ..Common import Common

Uwaga: zadziała to tylko wtedy, gdy uruchomisz Pythona jako moduł spoza pakietu. Na przykład:

python -m Proj

Oryginalny hacky sposób

Ta metoda jest nadal powszechnie używana w niektórych sytuacjach, w których tak naprawdę nigdy nie „instalujesz” swojego pakietu. Na przykład jest popularny wśród użytkowników Django.

Możesz dodać Common / do swojego sys.path (lista ścieżek, na które Python patrzy, aby importować rzeczy):

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'Common'))
import Common

os.path.dirname(__file__) po prostu podaje katalog, w którym znajduje się twój bieżący plik Pythona, a następnie przechodzimy do katalogu „Common /” i importujemy moduł „Common”.


2
Nie modyfikuj ręcznie ścieżki modułów Pythona, może to być tylko dla szybkich hacków. Nauka zarządzania pakietami Pythona przy użyciu distutils, setuptools itp. Jest zwykle wymaganą umiejętnością, która rozwiąże takie problemy.
— Sascha Gottfried

1
@SaschaGottfried całkowicie się zgadzam, chociaż jeśli nie tworzysz pakietu dystrybucyjnego, prawdopodobnie nie będzie to miało znaczenia. Na przykład w Django nigdy tak naprawdę nie instalujesz swojej aplikacji za pomocą distutils, więc powyższa metoda jest łatwym hackowaniem. Ale w każdym razie zredagowałem odpowiedź, podając, co bym teraz zrobił.
— Dave

33
Dziękuję, że odpowiedziałeś na właściwe pytanie, zamiast mówić o właściwej technice. Istnieje wiele dobrych powodów, aby dokonać importu względnego.
— shrewmouse

jak przejść o więcej niż jeden poziom?
— jxramos,

10
aby przejść o jeden poziom wyżej, użyj dodatkowej kropki na każdym poziomie. @jxramos ex: from ...myfileidzie do../../myfile
— WattsInABox

10

Zabawne, ten sam problem, który właśnie spotkałem, i otrzymuję tę pracę w następujący sposób:

łącząc z poleceniem linux ln, możemy bardzo uprościć sprawę:

1. cd Proj/Client
2. ln -s ../Common ./

3. cd Proj/Server
4. ln -s ../Common ./

A teraz, jeśli chcesz importować some_stuffz pliku: Proj/Common/Common.pydo swojego pliku:, Proj/Client/Client.pytak jak to:

# in Proj/Client/Client.py
from Common.Common import some_stuff

I to samo dotyczy Proj/Server, Działa również dla setup.pyprocesu, to samo pytanie omówione tutaj , mam nadzieję, że pomoże!


10

Nie rób importu względnego.

Z PEP8 :

Względny import w przypadku importu wewnątrz paczki jest wysoce odradzany.

Umieść cały kod w jednym super pakiecie (np. „Myapp”) i używaj podpakietów dla klienta, serwera i wspólnego kodu.

Aktualizacja: „ Python 2.6 i 3.x obsługuje prawidłowe importowanie względne (...) ”. Zobacz odpowiedzi Dave'a, aby uzyskać więcej informacji.


1
Wyobraź sobie, że dodajesz kod na końcu klienta i serwera po if __name__ == "__main__":wierszu „ ”. Oznacza to, że chcesz móc ich używać jako samodzielnych skryptów. Jak to zrobić poprawnie? Myślę, że jest to bardzo powszechny przypadek użycia, który powinien być obsługiwany. Dlaczego jest to odradzane?
— Jabba

83
Jestem zaskoczony, że „nie rób tego” jest odpowiedzią dopuszczone do „Jak to zrobić ...” pytanie (dobrze, z wyjątkiem szyn <g>). Nie są sporadyczne powodów, aby to zrobić. Używam rozwiązania podobnego do tego, które sugeruje Dave.
— Tom Wilson

1
@TomWilson: To nie jest czysta odpowiedź „nie rób tego”. Poniżej znajduje się „zrób to w ten sposób”.
— Michał Šrajer

2
Ktoś powinien powiedzieć chłopakom z Numpy! Używają TONY względnego importu!
— Austin A,

12
Ta odpowiedź nie ma zastosowania do aktualnych wersji Pythona. Cytowanej części nie ma już w PEP 8. Obecnie brzmi ona następująco: „jawny import względny jest akceptowalną alternatywą dla importu absolutnego, szczególnie w przypadku złożonych układów opakowań, w których użycie importu absolutnego byłoby niepotrzebnie
— rozwlekłe

8

Wykonanie względnego importu jest absolutnie OK! Oto, co robi mały 'ol me:

#first change the cwd to the script path
scriptPath = os.path.realpath(os.path.dirname(sys.argv[0]))
os.chdir(scriptPath)

#append the relative location you want to import from
sys.path.append("../common")

#import your module stored in '../common'
import common.py

1
Ale lepiej wiedz, gdzie faktycznie wskazuje sys.argv [0] - to (prawdopodobnie) nie jest katalog, w którym byłeś, kiedy uruchamiałeś Pythona.
— CarlH,

To szybki hack, z wieloma pułapkami. Ale pytanie nie było nawet lepsze.
— Sascha Gottfried

1
To wyraźnie napisane, ale oryginalny hack w odpowiedzi Dave'a jest lepszy, ponieważ używa go __file__do uzyskania właściwej relacji z bieżącego pliku
— John Neuhaus

4

Domyślna metoda importu jest już „względna” i pochodzi z PYTHONPATH. PYTHONPATH jest domyślnie przypisywana do niektórych bibliotek systemowych wraz z folderem oryginalnego pliku źródłowego. Jeśli uruchomisz z -m, aby uruchomić moduł, bieżący katalog zostanie dodany do PYTHONPATH. Więc jeśli punkt wejścia twojego programu znajduje się wewnątrz Proj, użyjimport Common.Common powinno działać zarówno wewnątrz Server.py, jak i Client.py.

Nie rób względnego importu. Nie będzie działać tak, jak chcesz.


1
Jeśli to prawda, dlaczego w najpopularniejszych odpowiedziach tego nie ma? Czy to zadziała, czy nie?
— Anonimowy
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.