Яка різниця між модулем Python та пакетом Python?


576

Яка різниця між модулем Python та пакетом Python?

Дивіться також: Яка різниця між "пакунком" та "модулем" (для інших мов)


9
Я можу помилитися, але для мене: модуль - це в основному один файл python. Пакет - це папка з купою модулів (файлів python).
lc2817

36
Щоб вважатись пакетом, ця папка повинна містити __init__.pyфайл.
Джуліо Піанкастеллі

@ lc2817: це найпоширеніший випадок, але не потрібно, щоб модуль завантажувався з файлової системи, наприклад, дивіться from plumbum.cmd import lsреалізацію
jfs


Як співтовариство відрізняє між пакетами Python та пакетами, які використовуються для розповсюдження компонентів Python, таких як PyPI / колеса / тощо? Ці два мені здаються різними додатками слова "пакет".
davidA

Відповіді:


373

Модуль - це єдиний файл (або файли), які імпортуються під одним імпортом та використовуються. напр

import my_module

Пакет - це сукупність модулів у каталогах, які дають ієрархію пакунків.

from my_package.timing.danger.internets import function_of_love

Документація на модулі

Ознайомлення з пакетами


54
Коли ви говорите: "Модуль - це один файл (або файли), які імпортуються під одним імпортом", чи можете ви пояснити ситуацію, коли модуль має більше одного файлу? Або я неправильно читаю, що ти маєш на увазі?
Користувач

5
Вам не потрібен файл для створення модуля, наприклад, ви можете імпортувати модуль із zip-файлу. Те саме для пакетів. У Python існує лише один клас для модулів / пакетів. Пакет - це просто модуль з __path__атрибутом.
jfs

33
Пакети теж є модулями . Вони просто розфасовані по-різному; вони формуються комбінацією каталогу плюс __init__.pyфайл. Вони є модулями, які можуть містити інші модулі.
Martijn Pieters

15
@Jacquot впевнений, див. Система імпорту у довідковій документації: Важливо пам’ятати, що всі пакети є модулями .
Martijn Pieters

6
@Jacquot: та словник "пакунку" : модуль Python, який може містити підмодулі або рекурсивно, підпакети. Технічно пакет - це модуль Python з __path__атрибутом.
Martijn Pieters

556

Будь-який файл Python є модулем , його ім'я - основне ім'я файлу без .pyрозширення. Пакет являє собою набір модулів Python: в той час як модуль являє собою один файл Python, пакет являє собою каталог модулів Python , що містять додатковий __init__.pyфайл, щоб відрізнити пакет з каталогу , який тільки , трапляється, містить набір сценаріїв Python. Пакети можуть бути вкладені на будь-яку глибину, за умови, що відповідні каталоги містять власний __init__.pyфайл.

Відмінність між модулем та пакетом, здається, виконується саме на рівні файлової системи. Коли ви імпортуєте модуль або пакет, відповідний об'єкт, створений Python, завжди має тип module. Зауважте, проте, коли ви імпортуєте пакет, __init__.pyбезпосередньо видні лише змінні / функції / класи у файлі цього пакету, а не підпакети чи модулі. Як приклад, розглянемо xmlпакет у стандартній бібліотеці Python: його xmlкаталог містить __init__.pyфайл і чотири підкаталоги; підкаталог etreeмістить __init__.pyфайл і, серед інших, ElementTree.pyфайл. Подивіться, що відбувається при спробі інтерактивного імпорту пакета / модулів:

>>> 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>

У Python також є вбудовані модулі, такі як sys, написані на C, але я не думаю, що ти мав на увазі розглядати це у своєму питанні.


9
Дякуємо за те, що явно зазначили, що відповідний об’єкт, створений Python, завжди має тип module. Я в процесі написання налагоджувача і переживав, що мій налагоджувач невірно сказав, що мої пакети були modules.
ArtOfWarfare

8
Файли @jolvi Python з ім'ям файлу, що містить тире, все ще можна імпортувати як модулі, тільки не зі звичайним importоператором, тому що тире не дозволено в ідентифікаторах Python. Використовуйте importlib.import_module()замість цього.
Джуліо Піанкастеллі

2
@jolvi Я не є. Де в моєму коментарі ви це читаєте? Я просто кажу, що, якщо у вас трапляється або натрапляє на файл Python з тиреми на його ім'я, ви все одно можете імпортувати його як модуль. Я не заявляю про бажаний спосіб іменування файлу Python. Я впевнений, що ви можете знайти це десь в іншому місці: зазвичай настійно рекомендується уникати тире на користь підкреслень.
Джуліо Піанкастеллі

3
Що з новими в Python, підпакети або модулі, які за замовчуванням не доступні під час імпорту батьківського пакету, - це змусило мене спотикатися. Чи є певна причина для цього? І чи є загальна модель, як зробити підпакети або модулі (через їх повне ім'я) під час імпорту батьківського пакету?
sschuberth

2
@sschuberth Просто імпортуйте підпакети в init .py батьківського пакету.
Анна

33

З словника Python :

Важливо пам’ятати, що всі пакети є модулями, але не всі модулі є пакетами. Або кажучи іншим способом, пакети - це лише особливий вид модуля. Зокрема, будь-який модуль, який містить __path__атрибут, вважається пакетом.

Файли Python з тире в імені, як-от my-file.py, не можна імпортувати простим importоператором. За кодом - import my-fileце те саме, import my - fileщо призведе до виключення. Такі файли краще характеризувати як сценарії, тоді як файли, що імпортуються, - це модулі .


23

По-перше, майте на увазі, що за своїм точним визначенням модуль є об'єктом в пам'яті інтерпретатора Python, який часто створюється зчитуванням одного або декількох файлів з диска. Хоча ми можемо неофіційно називати файл диска типу a/b/c.py"модуль", він насправді не стає ним, поки він не поєднується з інформацією з кількох інших джерел (таких як sys.path) для створення об'єкта модуля.

(Зауважте, наприклад, що два модулі з різними іменами можна завантажувати з одного файлу залежно від sys.pathта інших параметрів. Це саме те, що відбувається з python -m my.moduleподальшим import my.moduleінтерпретатором; буде два об'єкти модуля, __main__і my.moduleобидва створені з того самого файлу на диску,. my/module.py)

Пакет являє собою модуль , який може мати підмодулі ( в тому числі підпакетів). Не всі модулі можуть це зробити. Як приклад, створіть невелику ієрархію модулів:

$ mkdir -p a/b
$ touch a/b/c.py

Переконайтесь, що немає інших файлів під a. Запустіть інтерпретатор Python 3.4 або пізнішої версії (наприклад, з python3 -i) та вивчіть результати наступних тверджень:

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'>

Модулі aі a.bє пакетами (насправді певний вид пакунків називається "пакетом простору імен", хоча тут ми не будемо турбуватися про це). Однак модуль a.b.cне є пакетом. Ми можемо продемонструвати це, додавши ще один файл a/b.pyдо структури каталогу вище та запустивши новий інтерпретатор:

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 забезпечує завантаження всіх батьківських модулів перед завантаженням дочірнього модуля. Зверху він виявляє, що a/це каталог, і таким чином створює пакет простору імен a, і a/b.pyце вихідний файл Python, який він завантажує та використовує для створення (непакетного) модуля a.b. На даний момент ви не можете мати модуль, a.b.cоскільки a.bце не пакет, і тому не може бути підмодулів.

Тут також можна побачити, що пакетний модуль aмає __path__атрибут (пакунки повинні мати це), але непакетний модуль a.bцього не має.


1
Якщо ви ще цього не зробили, поверніться та огляньте приклади цієї відповіді.
Donal Lafferty

2

Пізня відповідь, ще одне визначення:

Пакет представлений імпортованим топ-об'єктом, який може бути або автономним модулем, або __init__.pyспеціальним модулем як топ-об'єкт із набору модулів у структурі підкаталогу.

Отже, фізично пакет - це розподільний блок, який забезпечує один або кілька модулів.


1
Я відчуваю, що в Python є два визначення для пакету, і вони відрізняються. Здається, ваша відповідь поєднує їх разом. Власне кажучи, пакет python - це каталог з __init__.pyмодулем всередині, але якщо ви говорите про дистрибутивні блоки (зазвичай через PyPI), то це цілком інший тип пакунків (як правило, визначений існуванням setup.py). Я вважаю, що ці два терміни використовують термін packageзаплутаним, і я говорив з початківцями Python, які вважають це надзвичайно дивовижним.
davidA

@davidA, це не тільки те, як ти себе почуваєш. Це було кодифіковано: packaging.python.org/glossary/#term-distribution-package (Дякую також за уточнення!)
Lorem Ipsum

0

Пакет - це також модуль, який може містити інші модулі, «прості модулі на основі файлів та пакети (підпакет)». Код, пов'язаний з типом пакету модуля, надходить у __init__.pyфайл.

import pack1
print(type(pack1))

тоді як модулі - це простий файл, який може містити функції, класи, код, який можна виконувати, після імпорту модуля він поводиться як об'єкт, за допомогою якого можна отримати доступ до ідентифікаторів, визначених у модулі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.