Tại sao các mô-đun Python đôi khi không nhập các mô-đun con của chúng?


88

Tôi nhận thấy một điều gì đó kỳ lạ hôm nay tôi muốn giải thích. Tôi không chắc chắn 100% làm thế nào để thậm chí cụm từ này như một câu hỏi, vì vậy google không có câu hỏi. Mô-đun ghi nhật ký không có quyền truy cập vào mô-đun logging.handlers vì một số lý do kỳ lạ. Hãy tự mình thử nếu bạn không tin tôi:

>>> import logging
>>> logging.handlers
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'handlers'
>>> import logging.handlers
>>> logging.handlers
<module 'logging.handlers' from '/usr/lib/python2.6/logging/handlers.pyc'>

Bất cứ ai có thể giải thích tại sao điều này xảy ra?

Câu trả lời:


119

Trong Python, các mô-đun cần được nhập trước khi chúng có thể truy cập được. import loggingchỉ nhập mô-đun ghi nhật ký. Điều đó xảy ra logginglà một gói có các mô-đun con, nhưng các mô-đun con đó vẫn không được tải tự động. Vì vậy, bạn cần nhập rõ ràng logging.handlerstrước khi có thể truy cập.

Nếu bạn đang tự hỏi tại sao có vẻ như đôi khi bạn không cần các lần nhập bổ sung đó: một số gói nhập một số hoặc tất cả các mô-đun con của chúng khi chúng được nhập - đơn giản bằng cách thực hiện các lần nhập đó trong __init__.pytệp của chúng . Trong các trường hợp khác, đó có thể là thứ khác mà bạn nhập, cũng được nhập logging.handlers. Việc nhập đoạn mã nào không quan trọng; miễn là thứ gì đó trong quy trình của bạn nhập logging.handlerstrước khi bạn truy cập, nó sẽ ở đó. Và đôi khi một mô-đun trông giống như một gói thực sự không phải là một, như osos.path. oskhông phải là một gói, nó chỉ nhập đúng mô-đun khác (cho nền tảng của bạn) và gọi nó path, chỉ để bạn có thể truy cập nó như os.path.


4

Tôi cũng mới sử dụng python và sau khi thực hành nhiều, giờ tôi có thể phân biệt giữa, gói (thư mục), mô-đun (.py), lớp, biến ... vv ...

nếu bạn muốn bất kỳ thư mục nào của mình là gói python - Nó phải chứa __init__.pytệp, thậm chí tệp trống sẽ làm được !!!

và như Thomas đã nói, bạn có thể nhập thêm mô-đun trong __init__.py nếu bạn muốn !!! nhưng các mô-đun / gói chỉ có thể truy cập được sau khi nhập nó ...

nếu bạn muốn nhập mọi thứ từ một mô-đun bạn có thể sử dụng

from logging import *

phần còn lại, bạn cũng có thể truy cập vào mô-đun trình xử lý như bên dưới,

from logging import handlers
print dir(handlers)


5
Vui lòng không sử dụng from module import *. Nó gần như luôn luôn là một sai lầm.
Thomas Wouters

Nếu bạn muốn mọi thứ trong một gói được nhập tự động, hãy nhập những lần nhập đó trong init .py, thay vì đặt tất cả trong init .py và thực hiện 'từ nhập gói *' ở đâu đó.
Thomas Wouters

2
@Pete: vì nó làm "ô nhiễm" không gian tên tiêu chuẩn dẫn đến sự mơ hồ và xung đột. Nếu tôi có import zipperzipper.open()bạn biết chính xác tôi đang gọi số mở nào. Ngược lại, from zipper import *theo sau open()là khóa mở hoặc khóa kéo tích hợp sẵn hoặc thứ gì khác. import zipper as zđược ưu tiên hơn nhiều nếu bạn cảm thấy mệt mỏi với việc nhậpzipper
nhắn từ

3
@Pete: Đó cũng là một vấn đề vì bạn có thể vô tình ghi đè lên một số vùng tên của mình. Tôi đã từng sử dụng từ numpy import *vì một số hàm numpy không hoạt động trừ khi bạn nhập tất cả numpy (lỗi thiết kế khủng khiếp trên phần IMO của chúng) nhưng numpy có một số lượng KHỔNG LỒ đối tượng mà nó nhập. Cuối cùng tôi đã ghi đè rất nhiều chức năng (tôi tin rằng bản sao là một ... Tôi quá mệt để kiểm tra). Bây giờ tôi nhập numpy dưới dạng np nếu tôi sẽ sử dụng numpy nhiều đến mức tôi không thể đứng để gõ nó nhiều lần.
chriscauley

2
@dustynachos, hàm numpy nào có lỗ hổng đó?
Winston Ewert

2

Thomas Wouters đã trả lời câu hỏi này rất tốt, nhưng than ôi, tôi chỉ tìm thấy câu hỏi này sau khi tìm thấy câu trả lời trong tài liệu gốc. Để đạt được điều đó, tôi nghĩ rằng tôi sẽ thêm nó vào với hy vọng nó sẽ xuất hiện gần đầu công cụ tìm kiếm hơn trong tương lai.

CÂU HỎI

Tại sao lỗi: ' AttributeError: module' module_name 'không có thuộc tính' sub_module_name 'xuất hiện mặc dù trình soạn thảo của tôi (ví dụ: Mã trực quan) tự động điền tên mô-đun phụ:

 import module_name
 module_name.sub_module_name(parameter)

CÂU TRẢ LỜI

Trình chỉnh sửa của bạn đang dựa trên tính năng tự động hoàn thành của nó dựa trên cấu trúc tệp của dự án của bạn chứ không phải dựa trên hành vi Python. Các mô-đun con không được nhập 'tự động' khi bạn nhập một mô-đun. Tham khảo Tài liệu Python để biết chi tiết về cách 'tự động' nhập các mô-đun con khi sử dụng

 import module_name

Đóng góp quan trọng với câu trả lời này là việc bổ sung AttributeError khi cố gắng nhập 'mô-đun' hoặc 'gói'

Hy vọng điều này sẽ giúp ai đó!


1

Gần đây tôi đã phải đối mặt với tình huống kỳ lạ tương tự. Vì vậy, tôi cá là bạn đã xóa một số thao tác nhập lib của bên thứ ba. Điều đó đã loại bỏ lib chứa from logging import handlershoặc from logging import *và cung cấp cho bạn handlers. Và trong tập lệnh khác, bạn đã có một cái gì đó giống như import loggingvà vừa mới sử dụng logging.handlersvà bạn nghĩ rằng đó là cách mọi thứ hoạt động như tôi đã làm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.