Sự khác biệt giữa mô-đun Python và gói Python là gì?
Xem thêm: Sự khác biệt giữa "gói" và "mô-đun" (đối với các ngôn ngữ khác)
__init__.py
tệp.
from plumbum.cmd import ls
triển khai
__init__.py
Sự khác biệt giữa mô-đun Python và gói Python là gì?
Xem thêm: Sự khác biệt giữa "gói" và "mô-đun" (đối với các ngôn ngữ khác)
__init__.py
tệp.
from plumbum.cmd import ls
triển khai
__init__.py
Câu trả lời:
Một mô-đun là một tệp (hoặc tệp) được nhập theo một lần nhập và sử dụng. ví dụ
import my_module
Một gói là một tập hợp các mô-đun trong các thư mục cung cấp một hệ thống phân cấp gói.
from my_package.timing.danger.internets import function_of_love
__path__
thuộc tính.
__init__.py
tập tin. Chúng là các mô-đun có thể chứa các mô-đun khác.
__path__
thuộc tính.
Bất kỳ tệp Python nào cũng là một mô-đun , tên của nó là tên cơ sở của tệp mà không có .py
phần mở rộng. Một gói là một tập hợp các module Python: trong khi một module là một file Python duy nhất, một gói là một thư mục của module Python chứa thêm __init__.py
tập tin, để phân biệt một gói từ một thư mục mà chỉ xảy ra để chứa một loạt các kịch bản Python. Các gói có thể được lồng vào bất kỳ độ sâu nào, miễn là các thư mục tương ứng chứa riêng chúng__init__.py
tệp .
Sự khác biệt giữa mô-đun và gói dường như chỉ giữ ở cấp hệ thống tệp. Khi bạn nhập một mô-đun hoặc một gói, đối tượng tương ứng được tạo bởi Python luôn có kiểu module
. Tuy nhiên, lưu ý, khi bạn nhập một gói, chỉ các biến / hàm / lớp trong __init__.py
tệp của gói đó được hiển thị trực tiếp, không phải các gói phụ hoặc mô-đun. Ví dụ, xem xét xml
gói trong thư viện chuẩn Python: thư mục của nó xml
chứa một __init__.py
tệp và bốn thư mục con; thư mục con etree
chứa một __init__.py
tệp và trong số các ElementTree.py
tệp khác. Xem điều gì xảy ra khi bạn cố gắng tương tác nhập gói / mô-đun:
>>> 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>
Trong Python cũng có các mô-đun tích hợp, chẳng hạn như sys
, được viết bằng C, nhưng tôi không nghĩ bạn có ý định xem xét những điều đó trong câu hỏi của bạn.
module
. Tôi đang trong quá trình viết một trình gỡ lỗi và lo lắng rằng trình gỡ lỗi của tôi không chính xác khi nói rằng các gói của tôi là module
s.
import
câu lệnh thông thường , vì dấu gạch ngang không được phép trong mã định danh Python. Sử dụng importlib.import_module()
thay thế.
Từ bảng chú giải Python :
Điều quan trọng cần nhớ là tất cả các gói là các mô-đun, nhưng không phải tất cả các mô-đun là các gói. Hoặc nói cách khác, các gói chỉ là một loại mô-đun đặc biệt. Cụ thể, bất kỳ mô-đun có chứa một
__path__
thuộc tính được coi là một gói.
Các tệp Python có dấu gạch ngang trong tên, như my-file.py
, không thể được nhập bằng một import
câu lệnh đơn giản . Code-khôn ngoan, import my-file
giống như import my - file
sẽ đưa ra một ngoại lệ. Các tệp như vậy được đặc trưng tốt hơn như các tập lệnh trong khi các tệp có thể nhập được là các mô-đun .
Trước tiên, hãy nhớ rằng, theo định nghĩa chính xác của nó, mô-đun là một đối tượng trong bộ nhớ của trình thông dịch Python, thường được tạo bằng cách đọc một hoặc nhiều tệp từ đĩa. Mặc dù chúng tôi có thể gọi một cách chính thức một tệp đĩa như a/b/c.py
"mô-đun", nhưng nó không thực sự trở thành một tệp cho đến khi nó kết hợp với thông tin từ một số nguồn khác (chẳng hạn như sys.path
) để tạo đối tượng mô-đun.
(Lưu ý, ví dụ, hai mô-đun có tên khác nhau có thể được tải từ cùng một tệp, tùy thuộc vào sys.path
các cài đặt khác. Đây chính xác là những gì xảy ra với python -m my.module
một import my.module
trình thông dịch theo sau; sẽ có hai đối tượng mô-đun __main__
và my.module
cả hai được tạo từ cùng một tệp trên đĩa , my/module.py
.)
Một gói là một mô-đun có thể có các mô hình con (bao gồm cả các gói con). Không phải tất cả các mô-đun có thể làm điều này. Ví dụ, tạo một hệ thống phân cấp mô-đun nhỏ:
$ mkdir -p a/b
$ touch a/b/c.py
Đảm bảo rằng không có tệp nào khác bên dưới a
. Bắt đầu trình thông dịch Python 3.4 trở lên (ví dụ: với python3 -i
) và kiểm tra kết quả của các câu lệnh sau:
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'>
Các mô-đun a
và a.b
là các gói (trên thực tế, một loại gói nhất định được gọi là "gói không gian tên", mặc dù chúng tôi không lo lắng về điều đó ở đây). Tuy nhiên, mô-đun a.b.c
không phải là một gói. Chúng tôi có thể chứng minh điều này bằng cách thêm một tệp khác a/b.py
vào cấu trúc thư mục ở trên và bắt đầu một trình thông dịch mới:
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 đảm bảo rằng tất cả các mô đun mẹ được tải trước khi mô đun con được tải. Ở trên nó thấy rằng đó a/
là một thư mục và do đó tạo ra một gói không gian tên a
và đó a/b.py
là một tệp nguồn Python mà nó tải và sử dụng để tạo ra một mô-đun (không phải gói) a.b
. Tại thời điểm này, bạn không thể có một mô-đun a.b.c
vì a.b
không phải là một gói và do đó không thể có các mô-đun con.
Bạn cũng có thể thấy ở đây mô-đun gói a
có một __path__
thuộc tính (các gói phải có điều này) nhưng mô-đun a.b
không gói không có.
Một câu trả lời muộn, nhưng một định nghĩa khác:
Một gói được đại diện bởi một thực thể hàng đầu được nhập khẩu, có thể là một mô-đun độc lập hoặc
__init__.py
mô-đun đặc biệt là thực thể hàng đầu từ một tập hợp các mô-đun trong cấu trúc thư mục con.
Vì vậy, vật lý một gói là một đơn vị phân phối, cung cấp một hoặc nhiều mô-đun.
__init__.py
mô-đun bên trong, nhưng nếu bạn nói về các đơn vị phân phối (thường thông qua PyPI) thì đây là một loại gói hoàn toàn khác (thường được xác định bởi sự tồn tại của setup.py
). Tôi thấy hai cách sử dụng thuật ngữ này package
gây nhầm lẫn và tôi đã nói chuyện với một số người mới bắt đầu Python, người thấy nó hoàn toàn hoang mang.
Gói cũng là một mô-đun có thể chứa các mô-đun khác, 'mô-đun dựa trên tệp đơn giản và gói (gói phụ)'. Mã liên quan đến loại gói mô-đun đi vào __init__.py
tệp.
import pack1
print(type(pack1))
trong khi các mô-đun là một tệp đơn giản có thể chứa các hàm, các lớp, mã có thể chạy được, v.v. sau khi nhập một mô-đun, nó hoạt động giống như một đối tượng mà bạn có thể truy cập các định danh được xác định trong mô-đun.