Jaka jest różnica między modułem Python a pakietem Python?

576

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)

Dave
źródło
9
Mogę się mylić, ale dla mnie: moduł to w zasadzie jeden plik Pythona. Pakiet to folder z wieloma modułami (plikami python).
lc2817,
36
Aby zostać uznanym za pakiet, ten folder musi zawierać __init__.pyplik.
Giulio Piancastelli
@ lc2817: jest to najczęstszy przypadek, ale nie jest konieczne ładowanie modułu z systemu plików, np. patrz from plumbum.cmd import lsimplementacja
jfs
4
@GiulioPiancastelli: W Pythonie 3.3+ pakiety przestrzeni nazw nie używają__init__.py
jfs
Jak społeczność rozróżnia pakiety Python od pakietów używanych do dystrybucji komponentów Python, takich jak PyPI / wheels / etc? Te dwa wydają mi się różnymi zastosowaniami słowa „pakiet”.
davidA

Odpowiedzi:

373

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

Dokumentacja modułów

Wprowadzenie do pakietów

Jakob Bowyer
źródło
54
Kiedy mówisz: „Moduł to pojedynczy plik (lub pliki) importowane w ramach jednego importu”, czy możesz wyjaśnić sytuację, w której moduł jest więcej niż jednym plikiem? A może źle rozumiem, co masz na myśli?
Użytkownik
5
Nie potrzebujesz pliku, aby utworzyć moduł, np. Możesz zaimportować moduł z pliku zip. To samo dotyczy pakietów. W Pythonie jest tylko jedna klasa modułów / pakietów. Pakiet to tylko moduł z __path__atrybutem.
jfs
33
Pakiety są również modułami . Są po prostu inaczej pakowane; są one tworzone przez połączenie katalogu plus __init__.pypliku. Są to moduły, które mogą zawierać inne moduły.
Martijn Pieters
15
@Jacquot na pewno zobacz System importowania w dokumentacji źródłowej: Należy pamiętać, że wszystkie pakiety są modułami .
Martijn Pieters
6
@Jacquot: oraz glosariusz „pakiet” : moduł Pythona, który może zawierać submoduły lub rekursywnie__path__
Martijn Pieters
556

Każdy plik Pythona jest modułem , którego nazwa jest podstawową nazwą pliku bez .pyrozszerzenia. Pakiet jest zbiorem modułów Pythona: podczas gdy moduł jest pojedynczy plik Python, pakiet jest katalogiem modułów Pythona zawierających dodatkowy __init__.pyplik, 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__.pyplik.

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__.pypliku tego pakietu są bezpośrednio widoczne, a nie podpakiety lub moduły. Jako przykład rozważ xmlpakiet w standardowej bibliotece Pythona: jego xmlkatalog zawiera __init__.pyplik i cztery podkatalogi; podkatalog etreezawiera __init__.pyplik i, między innymi, ElementTree.pyplik. 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.

Giulio Piancastelli
źródło
9
Dziękujemy za wyraźne wspomnienie, że odpowiedni obiekt utworzony przez Python jest zawsze typu module. Jestem w trakcie pisania debugera i martwiłem się, że mój debuger nie powiedział, że moje pakiety to modules.
ArtOfWarfare
8
@jolvi Pliki Pythona o nazwie zawierającej myślniki mogą być nadal importowane jako moduły, ale nie ze zwykłą importinstrukcją, ponieważ myślniki nie są dozwolone w identyfikatorach Pythona. Użyj importlib.import_module()zamiast tego.
Giulio Piancastelli
2
@jolvi Nie jestem. Gdzie w moim komentarzu to czytasz? Mówię tylko, że jeśli zdarzy się, że natrafisz na plik Pythona z myślnikami w jego nazwie, możesz go zaimportować jako moduł. Nie wypowiadam się na temat preferowanego sposobu nazewnictwa pliku Python. Jestem pewien, że znajdziesz to gdzie indziej: zwykle zdecydowanie zaleca się unikanie myślników na korzyść podkreślenia.
Giulio Piancastelli
3
To, że jestem nowy w Pythonie, domyślnie nie są dostępne sub-paczki lub moduły podczas importowania pakietu nadrzędnego. Czy ma to jakiś szczególny powód? Czy istnieje wspólny wzorzec, w jaki sposób udostępniać sub-paczki lub moduły (poprzez ich pełną nazwę) podczas importowania pakietu nadrzędnego?
sschuberth
2
@sschuberth Wystarczy zaimportować podpakiety w init .py pakietu nadrzędnego.
Anna
33

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 importinstrukcji. Pod względem kodu import my-filejest to ten sam, import my - filektóry spowoduje wyjątek. Takie pliki lepiej scharakteryzować jako skrypty, podczas gdy pliki do importu to moduły .

Jolvi
źródło
23

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.pathi innych ustawień. Dokładnie tak się dzieje z python -m my.modulenastępującym po nim import my.moduleinterpreterem; będą dwa obiekty modułu __main__i my.moduleoba 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 -iję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 ai a.bsą 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.cnie jest pakietem. Możemy to zademonstrować, dodając kolejny plik a/b.pydo 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.pyjest 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.cponieważ a.bnie jest on pakietem, a zatem nie możesz mieć podmodułów.

Można również zobaczyć tutaj, że moduł pakietu ama __path__atrybut (pakiety muszą to mieć), ale moduł inny niż pakiet a.bnie.

cjs
źródło
1
Jeśli jeszcze tego nie zrobiłeś, wróć i przejrzyj przykłady zawarte w tej odpowiedzi.
Donal Lafferty
2

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__.pymoduł 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.

replika
źródło
1
Wydaje mi się, że istnieją dwie definicje pakietu w Pythonie i są one różne. Twoja odpowiedź wydaje się łączyć je razem. Ściśle mówiąc, pakiet python jest katalogiem z __init__.pymoduł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 packagemylące i rozmawiałem z niektórymi początkującymi w Pythonie, którzy uważają je za całkowicie oszałamiające.
davidA
@davidA, To nie tylko to, jak się czujesz. Zostało skodyfikowane: opakowanie.python.org/glossary/#term-distribution-package (Dziękujemy za wyjaśnienie!)
Lorem Ipsum
0

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__.pypliku.

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.

Anil Kumar
źródło