2010-11-03 28 views
10

Tôi không rõ cách đặt tên chính xác câu hỏi này.Ưu tiên nhập khẩu Python: gói hoặc mô-đun?

Trường hợp 1

Giả sử rằng tôi có cấu trúc thư mục sau đây.

foo 
| 
+- bar/__init__.py 
| 
+- bar.py 

Nếu tôi có

from foo import bar 

Làm thế nào để tôi biết mà bar (bar.py hoặc bar/__init__.py) đang được nhập khẩu? Có cách nào dễ dàng để tự động phát hiện điều này xảy ra không?

Trường hợp 2

foo 
| 
+- foo.py 
| 
+- other.py 

Nếu other.py có dòng

import foo 

Làm thế nào để tôi biết được foo (foo hoặc foo.foo) đang được nhập khẩu? Một lần nữa, là tehre bất kỳ cách dễ dàng để tự động phát hiện điều này xảy ra?

+2

Cách dễ dàng để phát hiện nó: có dòng đầu tiên bar.py của được 'print (" thanh .py import ")' – nmichaels

+2

Tôi nên có RTFM-ed. http://docs.python.org/tutorial/modules.html là một tài nguyên tuyệt vời. –

+0

Có cách nào để buộc chương trình sử dụng cách diễn giải này hay cách khác không? – Sobi

Trả lời

6

TLDR; một gói được ưu tiên hơn một mô-đun cùng tên nếu chúng nằm trong cùng một thư mục.

Từ các tài liệu:

"Khi một module có tên spam được nhập khẩu, tìm kiếm thông dịch viên cho một file có tên spam.py trong thư mục hiện, và sau đó trong danh sách các thư mục được xác định bởi các biến môi trường PYTHONPATH. Điều này có cùng cú pháp với biến shell PATH, đó là danh sách các tên thư mục. "

Đây là một chút sai lầm vì người phiên dịch cũng sẽ tìm kiếm một gói phần mềm được gọi là spam (một thư mục gọi spam chứa một tập tin __init__.py). Vì các mục nhập thư mục được sắp xếp trước khi tìm kiếm, các gói được ưu tiên hơn các mô đun có cùng tên nếu chúng nằm trong cùng một thư mục vì spam xuất hiện trước spam.py.

Lưu ý rằng "thư mục hiện tại" có liên quan đến đường dẫn tập lệnh chính (đường dẫn nơi __name__ == '__main__' is True). Vì vậy, nếu bạn đang ở số /home/billg, hãy gọi /foo/bar.py, "thư mục hiện tại" đề cập đến /foo.

+1

Mọi thứ đã thay đổi chưa? bởi vì tôi dường như không nhận được thư mục hiện tại được thêm vào như bạn đề xuất. Các tài liệu hiện trạng, "Khi một mô-đun có tên là thư rác được nhập khẩu, người thông dịch đầu tiên tìm kiếm một mô-đun tích hợp với tên đó. Nếu không tìm thấy, nó sẽ tìm kiếm một tệp có tên spam.py trong danh sách các thư mục do sys.path biến. " Và tôi không thấy rằng "thư mục hiện tại" được liệt kê. Nhưng kể từ khi tôi bị mất có lẽ tôi là sự hiểu lầm? – PatrickT

+1

Và (tôi có thể hiểu lầm tất cả điều này) một câu trả lời stackoverflow trước đó nói, "Python không thêm thư mục hiện tại vào sys.path, mà là thư mục mà tập lệnh đang ở." http://stackoverflow.com/questions/2325923/how-to-fix-importerror-no-module-named-error-in-python – PatrickT

+0

Điều này dường như không trả lời ** Trường hợp 1 ** – qff

0

trong trường hợp đầu tiên mà bạn đang cố gắng để nhập khẩu thanh hàm từ tập tin 'foo.py'

Trong thứ hai bạn đang cố gắng để nhập khẩu các tập tin 'foo.py'

2

Gói (thư mục với __init__.py) được ưu tiên hơn mô-đun. Tài liệu về thực tế này rất khó tìm nhưng bạn có thể thấy điều này trong nguồn: python 2.7, python 3.6 (nhờ @qff để tìm).

Bạn cũng sẽ cần một __init__.py trong thư mục foo để ví dụ của bạn hoạt động.

Nếu other.py là bên trong foo/ sau đó nó sẽ được tải foo.py (không phải là thư mục foo/) bởi vì nó sẽ tìm trong thư mục hiện hành đầu tiên (trừ khi bạn đã chơi với PYTHONPATH hoặc sys.path).

+0

Làm thế nào để bạn biết nó được ưu tiên? - Tôi không thể tìm thấy nó trong [tài liệu Python] (https://docs.python.org/2/tutorial/modules.html) – qff

+0

@qff Tôi đã thử nghiệm nó. Tôi cũng thử nghiệm python3 ngay bây giờ và nó có hành vi tương tự. Một liên kết đến tài liệu chính thức của thực tế sẽ là tốt. Nếu bạn tìm thấy một, xin vui lòng chỉnh sửa câu trả lời của tôi hoặc gửi bình luận và tôi sẽ chỉnh sửa nó. – kanaka

+0

Tìm thấy nó! (loại) - các mục của một thư mục được sắp xếp trước khi cố tải mỗi thư mục như một gói hoặc mô-đun. Điều này đảm bảo các gói được nạp trước. [Liên kết tới mã nguồn CPython] (https://github.com/python/cpython/blob/c30098c8c6014f3340a369a31df9c74bdbacc269/Lib/pkgutil.py#L235) – qff

5

từ một vỏ python:

from foo import bar 

print bar.__file__ 

nên cho bạn biết tập tin đã được nhập khẩu

Rob

+0

chưa thuộc tính __file__ trên python3 – gabn88

Các vấn đề liên quan