os.path
działa w zabawny sposób. Wygląda na to, że os
powinien to być pakiet z modułem podrzędnym path
, ale w rzeczywistości os
jest to normalny moduł, który robi magię, sys.modules
wstrzykując os.path
. Oto, co się dzieje:
Podczas uruchamiania Python ładuje kilka modułów do sys.modules
. Nie są one powiązane z żadnymi nazwami w twoim skrypcie, ale możesz uzyskać dostęp do już utworzonych modułów, kiedy w jakiś sposób je zaimportujesz.
sys.modules
to dykt, w którym buforowane są moduły. Kiedy importujesz moduł, jeśli został już gdzieś zaimportowany, pobiera instancję zapisaną w sys.modules
.
os
należy do modułów ładowanych podczas uruchamiania Pythona. Przypisuje swój path
atrybut modułowi ścieżki specyficznej dla systemu operacyjnego.
Wstrzykuje sys.modules['os.path'] = path
tak, że można " import os.path
" robić tak, jakby to był podmoduł.
Staram się myśleć os.path
jako moduł chcę użyć zamiast rzeczy w os
module , więc nawet jeśli nie jest to naprawdę to moduł podrzędny pakietu o nazwie os
, importować go coś jak to jest jeden i zawsze robięimport os.path
. Jest to zgodne z sposobem os.path
udokumentowania.
Nawiasem mówiąc, ten rodzaj struktury prowadzi do wielu wczesnych zamieszania programistów Pythona dotyczących modułów i pakietów oraz organizacji kodu. Dzieje się tak naprawdę z dwóch powodów
Jeśli myślisz o os
pakiecie i wiesz, że możesz zrobić import os
i mieć dostęp do modułu podrzędnego os.path
, możesz być później zaskoczony, że nie możesz tego zrobić import twisted
i automatycznie uzyskać dostęp twisted.spread
bez importowania go.
To jest mylące, że os.name
jest to normalna rzecz, ciąg znaków i os.path
moduł. Zawsze strukturyzuję swoje pakiety za pomocą pustych __init__.py
plików, tak aby na tym samym poziomie zawsze mieć jeden typ: moduł / pakiet lub inne rzeczy. Kilka dużych projektów Pythona stosuje to podejście, które ma tendencję do tworzenia bardziej ustrukturyzowanego kodu.
import os.path
sam i uważam, że to lepszy sposób. Przez „Jest to zgodne z dokumentacją os.path”, miałem na myśli, że ma on swoją własną stronę w dokumentacji pod adresem docs.python.org/library/os.path.html .os.py
rzeczywiście wstrzykuje dosys.modules['os.path']
. Dlatego właśniefrom os.path import something
działa. Byłem ciekawy, kiedy to zostało wprowadzone i sprawdziłem źródło. Ciekawostka: pochodzi z 1999 roku, po raz pierwszy dołączony do Pythona 1.5.2. Oryginalne zatwierdzenie jest tutaj .Zgodnie z PEP-20 autorstwa Tima Petersa, „Wyraźne jest lepsze niż niejawne” i „Czytelność liczy się”. Jeśli wszystko, czego potrzebujesz z
os
modułu, jest poniżejos.path
,import os.path
byłoby to bardziej szczegółowe i daj innym znać, na czym naprawdę Ci zależy.Podobnie PEP-20 mówi również, że „proste jest lepsze niż złożone”, więc jeśli potrzebujesz również rzeczy, które znajdują się pod bardziej ogólnym
os
parasolem,import os
byłoby preferowane.źródło
import os
naprawdę można być „prostym” w jakikolwiek znaczący sposób. Proste! = Krótkie.import os
iimport os.path
jest stuknięty, jeśli np potrzebyos.getcwd()
ios.path.isfile()
Ostateczna odpowiedź:
import os
i użyjos.path
. nieimport os.path
bezpośrednio.Z dokumentacji samego modułu:
źródło
os.path
modułu, który nie istnieje, ale dlaposixpath
."Instead of importing this module directly, import os and refer to this module as os.path."
znajduje sięposixpath.py
(lubmacpath.py
,ntpath.py
itd.). Jestem prawie pewien, że mają na myśli to, że nie należyimport posixpath
(co działa), ale raczej zaimportować moduł przez,os
aby zapewnić lepszą przenośność. Nie sądzę, że mają zamiar dać zalecenie, czyimport os
czyimport os.path
jest to korzystne.Co ciekawe, import os.path zaimportuje cały os. spróbuj wykonać następujące czynności w interaktywnym monicie:
Wynik będzie taki sam, jak gdybyś właśnie zaimportował os. Dzieje się tak, ponieważ os.path będzie odnosić się do innego modułu w zależności od posiadanego systemu operacyjnego, więc Python zaimportuje system operacyjny, aby określić, który moduł załadować dla ścieżki.
odniesienie
Z niektórymi modułami powiedzenie
import foo
się nie ujawnifoo.bar
, więc myślę, że to naprawdę zależy od projektu konkretnego modułu.Ogólnie rzecz biorąc, samo importowanie potrzebnych jawnych modułów powinno być nieznacznie szybsze. Na moim komputerze:
import os.path
:7.54285810068e-06
sekundyimport os
:9.21904878972e-06
sekundyTe czasy są na tyle bliskie, że można je pominąć. Twój program może wymagać użycia innych modułów od
os
teraz lub później, więc zwykle sensowne jest po prostu poświęcenie dwóch mikrosekund i użycie go,import os
aby uniknąć tego błędu w późniejszym czasie. Zwykle opowiadamimport os.path
się po prostu za importowaniem systemu operacyjnego jako całości, ale widzę, dlaczego niektórzy woleliby być technicznie bardziej wydajni i przekazać czytelnikom kod, który jest jedyną częściąos
modułu, która będzie musiała zostać użyta. Zasadniczo sprowadza się to do pytania o styl w mojej głowie.źródło
from os import path
spowoduje, że wywołania ścieżki będą jeszcze szybsze, jeśli problemem jest szybkość.Zdrowy rozsądek działa tutaj:
os
jest modułem i teżos.path
jest modułem. Po prostu zaimportuj moduł, którego chcesz użyć:Jeśli chcesz skorzystać z funkcjonalności w
os
module to importujos
.Jeśli chcesz skorzystać z funkcjonalności w
os.path
module to importujos.path
.Jeśli chcesz korzystać z funkcjonalności w obu modułach, zaimportuj oba moduły:
Na przykład:
Lib / idlelib / rpc.py używa
os
i importujeos
.Lib / idlelib / idle.py używa
os.path
i importujeos.path
.Lib / surepip / init .py używa obu i importuje oba.
źródło
Nie udało się znaleźć żadnego ostatecznego odniesienia, ale widzę, że przykładowy kod dla os.walk używa os.path, ale tylko importuje os
źródło