PYTHONPATH so với sys.path


92

Một nhà phát triển khác và tôi không đồng ý về việc liệu PYTHONPATH hoặc sys.path có nên được sử dụng để cho phép Python tìm một gói Python trong thư mục người dùng (ví dụ: phát triển) hay không.

Chúng tôi có một dự án Python với cấu trúc thư mục điển hình:

Project
    setup.py
    package
        __init__.py
        lib.py
        script.py

Trong script.py, chúng ta cần làm import package.lib. Khi gói được cài đặt trong site-package, script.py có thể tìm thấy package.lib.

Tuy nhiên, khi làm việc từ một thư mục người dùng, cần phải thực hiện một việc khác. Giải pháp của tôi là đặt PYTHONPATH của tôi bao gồm "~ / Project". Một nhà phát triển khác muốn đặt dòng mã này vào đầu script.py:

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

Vì vậy, Python có thể tìm thấy bản sao cục bộ của package.lib.

Tôi nghĩ đây là một ý tưởng tồi, vì dòng này chỉ hữu ích cho các nhà phát triển hoặc những người chạy từ một bản sao cục bộ, nhưng tôi không thể đưa ra lý do chính đáng tại sao đó là một ý tưởng tồi.

Chúng ta có nên sử dụng PYTOHNPATH, sys.path hay không?


4
Có vẻ như các phiếu bầu và câu trả lời được chia khá đồng đều với một chút nghiêng về việc sử dụng PYTHON_PATH mặc dù đây có thể là nhiễu lấy mẫu hoặc xu hướng không chủ ý từ câu hỏi.
AJP

Câu trả lời:


42

Nếu lý do duy nhất để sửa đổi đường dẫn là dành cho các nhà phát triển làm việc từ cây làm việc của họ, thì bạn nên sử dụng một công cụ cài đặt để thiết lập môi trường cho bạn. virtualenv rất phổ biến và nếu bạn đang sử dụng setuptools, bạn có thể chỉ cần chạy setup.py developđể cài đặt bán cây làm việc trong cài đặt Python hiện tại của mình.


10
Bạn có thể giải thích rõ hơn một chút về điều này không? Ngay cả khi bạn thiết lập một môi trường conda / virtualenv, thì điều này sẽ đặt toplevel dir trên đường dẫn python của bạn như thế nào?
compguy24

38

Tôi ghét PYTHONPATH. Tôi thấy việc đặt trên cơ sở từng người dùng (đặc biệt là đối với người dùng daemon) và theo dõi khi các thư mục dự án di chuyển xung quanh rất khó chịu và khó chịu. Tôi muốn đặt sys.pathtrong các tập lệnh gọi cho các dự án độc lập.

Tuy nhiên sys.path.appendkhông phải là cách để làm điều đó. Bạn có thể dễ dàng nhận được các bản sao và nó không sắp xếp .pthcác tệp. Tốt hơn (và dễ đọc hơn): site.addsitedir.

script.pythường sẽ không phải là nơi thích hợp hơn để làm điều đó, vì nó nằm bên trong gói bạn muốn cung cấp trên đường dẫn. Các mô-đun thư viện chắc chắn không được chạm vào sys.pathchính chúng. Thay vào đó, bạn thường có một tập lệnh băm bên ngoài gói mà bạn sử dụng để khởi tạo và chạy ứng dụng và trong tập lệnh trình bao bọc tầm thường này, bạn sẽ đặt các chi tiết triển khai như sys.path-frobbing.


16
Vấn đề site.addsitedirlà nó appendbật sys.path, nghĩa là một gói đã cài đặt sẽ được ưu tiên hơn gói cục bộ đang phát triển (và có thể xảy ra hiện tượng giật tóc sau đó). sys.path.insert(0...là cần thiết để vượt qua điều đó.
Eli Bendersky

5
@EliBendersky: nên được sys.path.insert(1. stackoverflow.com/q/10095037/125507
endolith

12

Nói chung, tôi sẽ coi việc thiết lập một biến môi trường (như PYTHONPATH) là một việc làm không tốt. Mặc dù điều này có thể tốt cho một lần gỡ lỗi nhưng sử dụng điều này như
một cách thực hành thường xuyên có thể không phải là một ý kiến ​​hay.

Việc sử dụng biến môi trường dẫn đến các tình huống như "nó hoạt động với tôi" khi một số người
khác báo cáo sự cố trong cơ sở mã. Ngoài ra, người ta cũng có thể thực hiện cùng một thực tiễn với môi trường thử nghiệm, dẫn đến các tình huống như các bài kiểm tra chạy tốt cho một nhà phát triển cụ thể nhưng có thể thất bại khi một số người khởi chạy các bài kiểm tra.


5

Tôi nghĩ rằng trong trường hợp này sử dụng PYTHONPATH là một điều tốt hơn, chủ yếu là vì nó không giới thiệu mã không cần thiết (có vấn đề).

Rốt cuộc, nếu bạn nghĩ về nó, người dùng của bạn không cần sys.paththứ đó, bởi vì gói của bạn sẽ được cài đặt vào các gói trang, bởi vì bạn sẽ sử dụng một hệ thống đóng gói.

Nếu người dùng chọn chạy từ "bản sao cục bộ", như bạn gọi nó, thì tôi đã quan sát thấy rằng phương pháp thông thường là tuyên bố rằng gói cần được thêm vào PYTHONPATH theo cách thủ công, nếu được sử dụng bên ngoài gói trang .


5

Cùng với nhiều lý do khác đã được đề cập, bạn cũng có thể chỉ ra rằng mã hóa khó

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

giòn vì nó giả định vị trí của script.py - nó sẽ chỉ hoạt động nếu script.py nằm trong Project / package. Nó sẽ bị hỏng nếu người dùng quyết định di chuyển / copy / symlink script.py (gần như) đến bất kỳ nơi nào khác.


2

Không hack PYTHONPATHcũng không phải sys.pathlà một ý tưởng hay do những lý do đã đề cập trước đó. Và để liên kết dự án hiện tại vào thư mục gói trang thực sự có một cách tốt hơn python setup.py develop, như được giải thích ở đây :

pip install --editable path/to/project

Nếu bạn chưa có setup.py trong thư mục gốc của dự án, thì cái này đủ tốt để bắt đầu với:

from setuptools import setup
setup('project')
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.