Jaka jest różnica między modułem Python a pakietem Python?
Zobacz także: Jaka jest różnica między „pakietem” a „modułem” (dla innych języków)
__init__.py
plik.
from plumbum.cmd import ls
implementacja
__init__.py
Jaka jest różnica między modułem Python a pakietem Python?
Zobacz także: Jaka jest różnica między „pakietem” a „modułem” (dla innych języków)
__init__.py
plik.
from plumbum.cmd import ls
implementacja
__init__.py
Odpowiedzi:
Moduł to pojedynczy plik (lub pliki), które są importowane w ramach jednego importu i używane. na przykład
import my_module
Pakiet to zbiór modułów w katalogach, które nadają hierarchię pakietów.
from my_package.timing.danger.internets import function_of_love
__path__
atrybutem.
__init__.py
pliku. Są to moduły, które mogą zawierać inne moduły.
__path__
Każdy plik Pythona jest modułem , którego nazwa jest podstawową nazwą pliku bez .py
rozszerzenia. Pakiet jest zbiorem modułów Pythona: podczas gdy moduł jest pojedynczy plik Python, pakiet jest katalogiem modułów Pythona zawierających dodatkowy __init__.py
plik, aby odróżnić pakiet z katalogu, który właśnie dzieje się zawierać kilka skryptów Pythona. Pakiety można zagnieżdżać na dowolnej głębokości, pod warunkiem, że odpowiednie katalogi zawierają własny __init__.py
plik.
Rozróżnienie między modułem a pakietem wydaje się utrzymywać tylko na poziomie systemu plików. Podczas importowania modułu lub pakietu odpowiedni obiekt utworzony przez Python jest zawsze typu module
. Pamiętaj jednak, że podczas importowania pakietu tylko zmienne / funkcje / klasy z __init__.py
pliku tego pakietu są bezpośrednio widoczne, a nie podpakiety lub moduły. Jako przykład rozważ xml
pakiet w standardowej bibliotece Pythona: jego xml
katalog zawiera __init__.py
plik i cztery podkatalogi; podkatalog etree
zawiera __init__.py
plik i, między innymi, ElementTree.py
plik. Zobacz, co się stanie, gdy spróbujesz interaktywnie zaimportować pakiet / moduły:
>>> import xml
>>> type(xml)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'etree'
>>> import xml.etree
>>> type(xml.etree)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'ElementTree'
>>> import xml.etree.ElementTree
>>> type(xml.etree.ElementTree)
<type 'module'>
>>> xml.etree.ElementTree.parse
<function parse at 0x00B135B0>
W Pythonie są również wbudowane moduły, takie jak sys
, napisane w C, ale nie sądzę, że powinieneś brać pod uwagę te pytania.
module
. Jestem w trakcie pisania debugera i martwiłem się, że mój debuger nie powiedział, że moje pakiety to module
s.
import
instrukcją, ponieważ myślniki nie są dozwolone w identyfikatorach Pythona. Użyj importlib.import_module()
zamiast tego.
Ze słownika Python :
Należy pamiętać, że wszystkie pakiety są modułami, ale nie wszystkie moduły są pakietami. Innymi słowy, pakiety są tylko specjalnym rodzajem modułu. W szczególności każdy moduł zawierający
__path__
atrybut jest uważany za pakiet.
Pliki Python z myślnikiem w nazwie, na przykład my-file.py
, nie mogą być importowane za pomocą prostej import
instrukcji. Pod względem kodu import my-file
jest to ten sam, import my - file
który spowoduje wyjątek. Takie pliki lepiej scharakteryzować jako skrypty, podczas gdy pliki do importu to moduły .
Po pierwsze, należy pamiętać, że w swojej dokładnej definicji moduł jest obiektem w pamięci interpretera języka Python, często tworzonym przez odczyt jednego lub więcej plików z dysku. Chociaż możemy nieformalnie wywołać plik dyskowy, taki jak a/b/c.py
„moduł”, tak naprawdę nie staje się nim, dopóki nie zostanie połączony z informacjami z kilku innych źródeł (np. sys.path
) W celu utworzenia obiektu modułu.
(Zauważ na przykład, że dwa moduły o różnych nazwach mogą być ładowane z tego samego pliku, w zależności od sys.path
i innych ustawień. Dokładnie tak się dzieje z python -m my.module
następującym po nim import my.module
interpreterem; będą dwa obiekty modułu __main__
i my.module
oba zostaną utworzone z tego samego pliku na dysku my/module.py
).
Pakiet jest modułem, który może być podmoduły (w tym podpakietów). Nie wszystkie moduły mogą to zrobić. Na przykład utwórz małą hierarchię modułów:
$ mkdir -p a/b
$ touch a/b/c.py
Upewnij się, że w obszarze nie ma innych plików a
. Uruchom interpreter python3 -i
języka Python 3.4 lub nowszy (np. Z ) i sprawdź wyniki następujących instrukcji:
import a
a ⇒ <module 'a' (namespace)>
a.b ⇒ AttributeError: module 'a' has no attribute 'b'
import a.b.c
a.b ⇒ <module 'a.b' (namespace)>
a.b.c ⇒ <module 'a.b.c' from '/home/cjs/a/b/c.py'>
Moduły a
i a.b
są pakietami (w rzeczywistości jest to pewien rodzaj pakietu zwany „pakietem przestrzeni nazw”, chociaż tutaj nie będziemy się tym martwić). Jednak moduł a.b.c
nie jest pakietem. Możemy to zademonstrować, dodając kolejny plik a/b.py
do powyższej struktury katalogów i uruchamiając świeżego interpretera:
import a.b.c
⇒ ImportError: No module named 'a.b.c'; 'a.b' is not a package
import a.b
a ⇒ <module 'a' (namespace)>
a.__path__ ⇒ _NamespacePath(['/.../a'])
a.b ⇒ <module 'a.b' from '/home/cjs/tmp/a/b.py'>
a.b.__path__ ⇒ AttributeError: 'module' object has no attribute '__path__'
Python zapewnia, że wszystkie moduły nadrzędne zostaną załadowane przed załadowaniem modułu podrzędnego. Powyżej stwierdza, że a/
jest to katalog, a zatem tworzy pakiet przestrzeni nazw a
, i a/b.py
jest to plik źródłowy Pythona, który ładuje i używa do utworzenia modułu (niebędącego pakietem) a.b
. W tym momencie nie możesz mieć modułu, a.b.c
ponieważ a.b
nie jest on pakietem, a zatem nie możesz mieć podmodułów.
Można również zobaczyć tutaj, że moduł pakietu a
ma __path__
atrybut (pakiety muszą to mieć), ale moduł inny niż pakiet a.b
nie.
Późna odpowiedź, jeszcze jedna definicja:
Pakiet jest reprezentowany przez zaimportowaną jednostkę najwyższą, która może być albo samodzielnym modułem, albo
__init__.py
moduł specjalny jako jednostka najwyższa z zestawu modułów w strukturze podkatalogu.
Zatem fizycznie pakiet jest jednostką dystrybucyjną, która zapewnia jeden lub więcej modułów.
__init__.py
modułem w środku, ale jeśli mówimy o jednostkach dystrybucyjnych (zwykle za pośrednictwem PyPI), to jest to całkowicie inny rodzaj pakietu (zwykle definiowany przez istnienie setup.py
). Uważam te dwa zastosowania tego terminu za package
mylące i rozmawiałem z niektórymi początkującymi w Pythonie, którzy uważają je za całkowicie oszałamiające.
Pakiet jest również modułem, który może zawierać inne moduły, „proste moduły oparte na plikach i pakiety (pod-pakiet)”. Kod związany z typem pakietu modułu trafia do __init__.py
pliku.
import pack1
print(type(pack1))
podczas gdy moduły są prostym plikiem, który może zawierać funkcje, klasy, kod uruchamialny itp. po zaimportowaniu modułu zachowuje się jak obiekt, za pomocą którego można uzyskać dostęp do identyfikatorów zdefiniowanych w module.