Tại sao sử dụng sys.path.append (path) thay vì sys.path.insert (1, path)?


88

Chỉnh sửa: dựa trên nhận xét của Ulf Rompe, điều quan trọng là bạn phải sử dụng "1" thay vì "0" , nếu không bạn sẽ phá vỡ sys.path .

Tôi đã làm python khá lâu rồi (hơn một năm) và tôi luôn bối rối tại sao mọi người khuyên bạn nên sử dụng sys.path.append()thay vì sys.path.insert(). Hãy để tôi chứng minh.

Giả sử tôi đang làm việc trên một mô-đun có tên PyWorkbooks (được cài đặt trên máy tính của tôi), nhưng tôi đang đồng thời làm việc trên một mô-đun khác (giả sử PyJob) kết hợp PyWorkbooks. Khi đang làm việc trên PyJob, tôi tìm thấy lỗi trong PyWorkbooks mà tôi đang sửa, vì vậy tôi muốn nhập phiên bản phát triển.

Có nhiều cách để làm việc trên cả hai (ví dụ: tôi có thể đặt dự án PyWorkbooks của mình bên trong PyJob), nhưng đôi khi tôi vẫn cần phải thử với đường dẫn. Tuy nhiên, tôi không thể chỉ đơn giản thực hiện một sys.path.append()thư mục mà PyWorkbooks đang ở . Tại sao? Bởi vì python sẽ tìm thấy PyWorkbooks đã cài đặt của tôi trước tiên!

Đây là lý do tại sao bạn phải thực hiện sys.path.insert (1, path_to_dev_pyworkbooks)

Tóm tắt:

sys.path.append(path_to_dev_pyworkbooks)
import PyWorkbooks # does NOT import dev pyworkbooks, imports installed one

hoặc là:

sys.path.insert(1, path_to_dev_pyworkbooks) # based on comments you should use **1 not 0**
import PyWorkbooks # imports correct file

Điều này đã gây ra một vài sự cố đối với tôi trong quá khứ và tôi thực sự muốn điều đó nếu chúng tôi (với tư cách là một cộng đồng) bắt đầu đề xuất sys.path.insert(1, path), như thể bạn đang chèn một đường dẫn theo cách thủ công, tôi nghĩ có thể nói rằng đó là đường dẫn bạn muốn để sử dụng!

Hay tôi có gì đó không ổn? Đó là một câu hỏi đôi khi làm tôi khó chịu và tôi muốn nó được mở!


3
Tôi đã làm xong sys.path.insert(1, dev_folder)nhưng vẫn không tìm thấy mô-đun nhà phát triển và chỉ sử dụng mô-đun đã cài đặt. Làm cách nào để sửa lỗi này?
endolith

Câu trả lời:


47

Nếu bạn có nhiều phiên bản của một gói / mô-đun, bạn cần phải sử dụng virtualenv (mỏ nhấn mạnh):

virtualenv là một công cụ để tạo môi trường Python cô lập.

Vấn đề cơ bản đang được giải quyết là một trong những phụ thuộc và phiên bản, và quyền gián tiếp. Hãy tưởng tượng bạn có một ứng dụng cần phiên bản 1 của LibFoo, nhưng một ứng dụng khác yêu cầu phiên bản 2. Làm thế nào bạn có thể sử dụng cả hai ứng dụng này? Nếu bạn cài đặt mọi thứ vào /usr/lib/python2.7/site-packages(hoặc bất kể vị trí tiêu chuẩn của nền tảng của bạn là gì), bạn rất dễ rơi vào tình huống vô tình nâng cấp một ứng dụng không nên nâng cấp.

Hay nói chung hơn, nếu bạn muốn cài đặt một ứng dụng và để nguyên nó thì sao? Nếu một ứng dụng hoạt động, bất kỳ thay đổi nào trong thư viện của ứng dụng đó hoặc phiên bản của các thư viện đó đều có thể phá vỡ ứng dụng.

Ngoài ra, nếu bạn không thể cài đặt các gói vào site-packagesthư mục chung thì sao? Ví dụ: trên một máy chủ được chia sẻ.

Trong tất cả những trường hợp này, virtualenvcó thể giúp bạn. Nó tạo ra một môi trường có các thư mục cài đặt riêng, không chia sẻ thư viện với các môi trường virtualenv khác (và tùy chọn cũng không truy cập các thư viện được cài đặt toàn cầu).

Đó là lý do tại sao mọi người insert(0, cho là sai - đó là một giải pháp stopgap không hoàn chỉnh cho vấn đề quản lý nhiều môi trường.


Cảm ơn, tôi đã mơ hồ biết một thứ như thế này tồn tại nhưng tôi chưa thực sự kiểm tra nó cho đến bây giờ. Vì vậy, những gì tôi sẽ phải làm với điều này là chạy mọi thứ từ trình thông dịch trong môi trường ảo ... cũng có thể hoạt động. Cảm ơn!
Garrett Berg

1
Đây là một gợi ý nhưng không trực tiếp trả lời câu hỏi (ví dụ: tôi có lý do chính đáng để không sử dụng virtualenvvà thực sự tôi đang tìm kiếm câu trả lời liên quan cho OP)
javadba

@javadba Điều đó có thể đúng với trường hợp của bạn, nhưng hầu hết những người hỏi câu hỏi này nên sử dụng venv.
agf

46

Nếu bạn thực sự cần sử dụng sys.path.insert, hãy cân nhắc để nguyên sys.path [0]:

sys.path.insert(1, path_to_dev_pyworkbooks)

Điều này có thể quan trọng vì mã của bên thứ 3 có thể dựa trên sự tuân thủ tài liệu sys.path :

Khi được khởi tạo khi khởi động chương trình, mục đầu tiên của danh sách này, đường dẫn [0], là thư mục chứa tập lệnh được sử dụng để gọi trình thông dịch Python.


13

bạn đang nhầm lẫn giữa khái niệm bổ sung và chi tiêu trước. mã sau đang được sử dụng trước:

sys.path.insert(1,'/thePathToYourFolder/')

nó đặt thông tin mới vào đầu (nói chính xác là thứ hai) của chuỗi tìm kiếm mà thông dịch viên của bạn sẽ trải qua. sys.path.append()đặt mọi thứ ở cuối chuỗi tìm kiếm.

bạn nên sử dụng một cái gì đó giống như virtualenvthay vì mã hóa thủ công các thư mục gói của bạn vào PYTHONPATHmọi lúc. để thiết lập các hệ sinh thái khác nhau phân tách các gói trang web của bạn và các phiên bản python khả thi, hãy đọc hai blog sau:

  1. giới thiệu hệ sinh thái trăn

  2. bootstrapping môi trường ảo python

nếu bạn quyết định chuyển sang con đường cô lập môi trường, bạn chắc chắn sẽ được lợi bằng cách xem xét virtualenvwrapper: http://www.doughellmann.com/docs/virtualenvwrapper/


1
Các liên kết "giới thiệu hệ sinh thái python", "môi trường ảo bootstrapping python" đã ngừng hoạt động, vui lòng xem xét khôi phục chúng.
Pradeep Singh
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.