2017-11-30 18 views
5

Vì vậy, tôi đang phát xung quanh với việc đóng gói một tập lệnh python mà tôi đã viết và nó có một mô-đun con, hãy gọi nó là submodule. Cấu trúc thư mục trông như thế này:Python có thể nhập một mô-đun chưa được cài đặt

cool_script/ 
    setup.py 
    cool_script.py 
    submodule/ 
    __init__.py 
    implementation.py 

Bây giờ, sau nhiều pip install .pip install -e . cuộc gọi, tôi có tình huống mà submodule thể được nhập khẩu toàn cầu. Bất kể ở đâu trên hệ thống của tôi, điều này sẽ luôn hoạt động:

$ python3 
[...] 
>>> import submodule 
>>> submodule.__file__ 
'/home/me/fake/path/cool_script/submodule/__init__.py' 

Nhưng tôi không biết tại sao.

Gói tôi đã thực hiện đã được gỡ cài đặt lại và pip không thể tìm thấy mô-đun con trong chỉ mục của nó. Không có gì trong dist-gói là một trong hai, tôi tự xóa cool_script.egg-link mà vẫn ngồi quanh đó:

$ ls /usr/local/lib/python3.4/dist-packages | ack cool 
$ ls /usr/local/lib/python3.4/dist-packages | ack submodule 
$ 

Các PYTHONPATH trống cũng như:

$ echo $PYTHONPATH 

$ 

Tại sao Python biết vị trí của submodule ? Làm thế nào tôi có thể tìm ra?

+0

Đã được cài đặt trong virtualenv chưa? Nó là một hệ thống Linux? –

+0

Đây là một hệ thống Linux thực sự, và không, tôi đã làm những thí nghiệm này trên môi trường toàn cầu của tôi. Tôi biết điều đó rất câm. Bài học kinh nghiệm, tôi đoán vậy. – iFreilicht

+0

Điều này nghe có vẻ ngu ngốc, nhưng bạn đã thử khởi động lại chưa? Có thể nó chỉ được lưu trữ ở đâu đó – RunOrVeith

Trả lời

3

Lần chạy đầu tiên python -c "import site; print(site.getsitepackages())". Nó sẽ in một danh sách như thế này:

['/XXX/something/site-packages'] 

Thông thường có một con đường duy nhất trong danh sách này, và nó trỏ đến một thư mục nơi pip cài đặt kịch bản của bạn. Bạn có thể ls vào đó nếu bạn tò mò: ls /XXX/something/site-packages/.

Thú vị hơn, tuy nhiên, pip đặt tệp "liên kết" trong thư mục đó khi bạn đang sử dụng lượt cài đặt của nhà phát triển (a.k.a. pip install -e). Tệp "liên kết" được đặt tên theo dự án ban đầu có phần mở rộng là .egg-link ở cuối.

Vì vậy, bạn có thể có tệp cool_script.egg-link trong thư mục đó. Và nếu bạn cố gắng in nó ra, bạn sẽ thấy rằng nội dung của nó liệt kê vị trí hệ thống tập tin gốc của mô-đun của bạn. Một cái gì đó như:

$ cat /XXX/something/site-packages/cool_script.egg-link 
/home/me/fake/path/cool_script/ 
. 

Đây là cách pip hồ sơ mà nó đã được cài đặt một cái gì đó trong chế độ nhà phát triển, nhưng nó không phải là cách Python thực sự biết làm thế nào để tìm thấy mô-đun của bạn (mà có thể đã được quá dễ dàng, phải không? -)).

Python không biết về .egg-link tệp nhưng nó đọc tất cả các tệp .pth trong thư mục site-packages để nhận thêm đường dẫn cho sys.path (*). Vì vậy, để Python có thể nhập lượt cài đặt chế độ nhà phát triển, pip ghi tất cả các đường dẫn của họ trong một tệp .pth thông thường được gọi là easy-install.pth (vì công cụ cũ easy-install thực sự đi tiên phong trong kỹ thuật đó). Và nếu bạn in ra tập tin đó, bạn sẽ nhận được danh sách đường dẫn tất cả dự án được cài đặt trong chế độ nhà phát triển:

$ cat /XXX/something/site-packages/easy-install.pth 
/home/me/fake/path/cool_script/ 
/home/me/another/project/ 

và bạn có thể kiểm tra xem thực sự tất cả những đường dẫn được liệt kê trong easy-install.pth thực sự được thêm vào sys.path của bạn .

(*) Về mặt kỹ thuật, một phần của Python đọc tệp .pth là mô-đun site thường được nhập tự động khi khởi động. Tuy nhiên, có một tùy chọn để vô hiệu hóa mô-đun site, ví dụ bằng cách sử dụng python -S. Trong trường hợp đó, bạn sẽ thấy rằng sys.path không chứa thư mục site-packages cũng như đường dẫn cài đặt của nhà phát triển.

+0

Đó là thư mục được liệt kê trong 'easy-install.pth'. Loại bỏ nó giải quyết được vấn đề! Cảm ơn bạn đã giải thích kỹ lưỡng. – iFreilicht

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