2013-04-03 14 views
5

Mục nhập đầu tiên của sys.path là thư mục của tập lệnh hiện tại, theo số docs. Trong thiết lập sau, tôi muốn thay đổi mặc định này. Hãy tưởng tượng cấu trúc thư mục sau:Khởi tạo đúng cách sys.path khi tập lệnh chính nằm trong một submodule

src/ 
    core/ 
     stuff/ 
     tools/ 
      tool1.py 
      tool2.py 
    gui/ 
     morestuff/ 
     gui.py 

Các kịch bản tool*.pygui.py đang dự định sẽ được chạy như kịch bản, như sau:

python src/core/tools/tool2.py 
python src/gui/gui.py 

Bây giờ tất cả các công cụ nhập khẩu từ src.core.stuff, và GUI cần gui.morestuff. Điều này có nghĩa là sys.path[0] phải trỏ đến src/, nhưng nó trỏ đến src/core/tools/ hoặc src/gui/ theo mặc định.

Tôi có thể điều chỉnh sys.path[0] trong mỗi kịch bản (với một cấu trúc như sau, ví dụ, vào đầu gui.py):

if __name__ == '__main__': 
    if sys.path[0]: sys.path[0] = os.path.dirname(os.path.abspath(sys.path[0])) 

Tuy nhiên, đây là loại không cần thiết, và nó trở nên tẻ nhạt cho một trưởng thành cơ sở mã với hàng nghìn tập lệnh. Tôi cũng biết -m switch:

python -m gui.gui 

Nhưng điều này đòi hỏi các thư mục hiện hành là src/.

Có cách nào tốt hơn để đạt được kết quả mong muốn hay không, ví dụ: bằng cách sửa đổi các tệp __init__.py?

EDIT: Đây là dành cho Python 2.7:

~$ python -V 
Python 2.7.3 
+0

Để bắt đầu có 'python -m core.tools.tool1' – Kos

+0

Bạn đang sử dụng phiên bản python nào? – filmor

+0

@filmor: Đã chỉnh sửa. – krlmlr

Trả lời

4

Bạn có ba tùy chọn cơ bản tại đây. Tôi đã trải qua cả ba trong cả môi trường sản xuất và các dự án cá nhân. Theo nhiều cách, họ xây dựng lẫn nhau. Tuy nhiên, lời khuyên của tôi là chỉ cần bỏ qua đến bài cuối cùng.

Vấn đề cơ bản là bạn cần thư mục ./src để nằm trong đường dẫn tìm kiếm trăn. Điều này thực sự là những gì bao bì python là tất cả về.

PYTHONPATH

Các đơn giản nhất, người sử dụng định nghĩa cách để điều chỉnh đường python của bạn là thông qua môi trường biến PYTHONPATH. Bạn có thể đặt nó ở thời gian chạy, làm một cái gì đó như:

PYTHONPATH=/src python src/gui/gui.py 

Bạn có thể dĩ nhiên cũng thiết lập này lên trong môi trường toàn cầu của bạn vì vậy hy vọng tất cả các quá trình cần nó sẽ tìm ra đúng PYTHONPATH. Nhưng, chỉ cần nhớ, bạn sẽ luôn luôn quên một. Thường vào lúc 3 giờ sáng khi nhiệm vụ cron của bạn cuối cùng cũng chạy.

Gói Site

Để tránh cần một biến môi trường, lựa chọn của bạn là khá nhiều bao gồm phần mềm của bạn trong một mục nhập hiện có trong đường dẫn nguồn, hoặc tìm một số cách bổ sung thêm một đường dẫn tìm kiếm mới.Vì vậy, điều này có thể có nghĩa là thả nội dung của thư mục src của bạn vào /usr/lib/python2.7/site-packages hoặc bất cứ nơi nào hệ thống của bạn site-packages được đặt.

Vì bạn có thể không thực sự bao gồm mã trong các gói trang web, bạn có thể tạo một liên kết tượng trưng cho hai gói con của bạn.

Đây là khóa học ít lý tưởng vì một số lý do. Nếu bạn không cẩn thận với việc đặt tên thì đột nhiên mọi chương trình python trên máy được tiếp xúc với các xung đột tên tiềm năng. Bạn đang hiển thị phần mềm của mình cho mọi người dùng trên máy. Bạn có thể gặp sự cố nếu python được cập nhật. Nếu bạn thêm một gói con mới, bây giờ bạn phải tạo một liên kết tượng trưng mới.

Cách tiếp cận tốt hơn một chút là bao gồm tệp .pth ở đâu đó trong gói trang web của bạn. Khi python gặp các tệp này, nó sẽ thêm nội dung (được cho là tên của một thư mục) vào đường dẫn tìm kiếm. Điều này tránh được vấn đề phải nhớ thêm một liên kết mới cho mỗi gói con mới.

virtualenv và đóng gói

Giải pháp tốt nhất là chỉ cần cắn đạn và làm bao bì python thực. Điều này, kết hợp với các công cụ tuyệt vời như virtualenv and pip cho phép bạn có môi trường python bị cô lập (hoặc bán cô lập).

Trong virtualenv, bạn sẽ có một tùy chỉnh site-packages chỉ cho dự án của bạn nơi bạn có thể dễ dàng cài đặt phần mềm vào đó, tránh tất cả các vấn đề của giải pháp trước đó. virtualenv cũng làm cho nó dễ dàng để duy trì các tập lệnh thực thi để môi trường python nó chạy dưới chính xác như bạn mong đợi.

Nhược điểm duy nhất là bạn phải viết và duy trì setup.py để hướng dẫn pip (trình cài đặt python) bao gồm phần mềm của bạn trong virtualenv. Nội dung sẽ là một cái gì đó như:

 
!/usr/bin/env python 
# -*- coding: utf-8 -*- 

from distutils.core import setup 


setup(
    name='myproject', 
    package_dir={'myproject': 'src'}, 
    scripts=['src/gui/gui.py', 'src/core/tools/tool1.py', 'src/core/tools/tool2.py'] 
) 

Vì vậy, để thiết lập môi trường này, nó sẽ giống như thế này:

virtualenv env 
env/bin/pip install -e setup.py 

Để chạy script của bạn, sau đó bạn chỉ muốn làm điều gì đó như:

env/bin/tool1.py 
+0

Cảm ơn câu trả lời rất chi tiết của bạn. Thật không may, bao bì không phải là một lựa chọn, phần mềm đang được phát triển trong một bản sao làm việc SVN. Tuy nhiên, tôi đã tự hỏi liệu tôi có thể sử dụng phương pháp thứ hai với bản sao làm việc SVN của tôi trong kết nối với virtualenv: Đặt một tệp '.pth' được định dạng thích hợp vào thư mục con' lib/python2.X/site-packages' của môi trường ảo hay không . Có suy nghĩ gì không? – krlmlr

+0

Sẽ không phải lựa chọn thứ ba cung cấp những gì bạn cần?Việc cài đặt một gói có 'pip install -e' sẽ cài đặt gói với các kịch bản lệnh, liên kết tới mã phát triển của bạn (thay vì cài đặt một bản sao), vì vậy mọi chỉnh sửa đối với mã trong repo sẽ tự động có sẵn trong virtualenv. –

+0

Việc đặt một tệp .pth thích hợp vào virtualenv về cơ bản là những gì 'pip install -e' làm cho bạn (theo câu trả lời của Josh) Nó cũng viết các trình giữ chỗ vào thư mục bin của bạn liên kết nó với cá thể thích hợp của python. – rhettg

5

Các chỉ cách chính thức được phê duyệt để chạy một kịch bản đó là trong một gói là bằng -m cờ. Trong khi bạn có thể chạy một kịch bản trực tiếp và cố gắng tự mình thực hiện các thao tác sys.path trong mỗi tập lệnh, thì đó có thể là một nỗi đau lớn. Nếu bạn di chuyển tập lệnh giữa các thư mục, thì lôgic để viết lại sys.path cũng có thể cần được thay đổi để phản ánh vị trí mới. Ngay cả khi bạn nhận được sys.path, nhập tương đối rõ ràng sẽ không hoạt động chính xác.

Bây giờ, thực hiện công việc python -m mypackage.mymodule yêu cầu bạn phải ở trong thư mục cấp cao nhất của dự án (src trong trường hợp của bạn) hoặc cho thư mục cấp cao nhất đó trên đường dẫn tìm kiếm Python. Yêu cầu bạn ở trong một thư mục cụ thể là khó xử, và bạn đã nói rằng bạn không muốn điều đó. Bắt src vào đường dẫn tìm kiếm là mục tiêu của chúng tôi sau đó.

Tôi nghĩ cách tiếp cận tốt nhất là sử dụng biến môi trường PYTHONPATH để trỏ trình thông dịch đến thư mục src của dự án để nó có thể tìm thấy gói của bạn từ bất kỳ đâu.

Giải pháp này đơn giản để thiết lập (biến môi trường có thể được đặt tự động trong .profile, .bashrc hoặc một số địa điểm tương đương khác) và sẽ hoạt động đối với bất kỳ số lượng tập lệnh nào. Nếu bạn di chuyển dự án của bạn, chỉ cần cập nhật cài đặt môi trường của bạn và bạn sẽ được tất cả các thiết lập, mà không cần phải làm bất kỳ công việc nhiều hơn cho mỗi kịch bản.

+0

Cảm ơn câu trả lời của bạn. Tôi muốn làm điều này để tránh phải đặt 'PYTHONPATH' ngay từ đầu ... – krlmlr

1

tôi muốn làm điều này để tránh việc phải thiết lập PYTHONPATH ở nơi đầu tiên

Có những nơi khác mà bạn có thể móc vào sys.path khởi Python, sử dụng các mô-đun site, đó là (theo mặc định) được tự động nhập khi Python khởi tạo.

Dựa trên mã này trong site.py ...

# Prefixes for site-packages; add additional prefixes like /usr/local here 
PREFIXES = [sys.prefix, sys.exec_prefix] 

... có vẻ như nếu mục đích là tập tin này được thiết kế để được sửa đổi sau khi cài đặt, đó là một lựa chọn, mặc dù nó cũng cung cấp các cách khác mà bạn có thể ảnh hưởng đến sys.path, ví dụ: bằng cách đặt một tệp .pth ở đâu đó trong thư mục site-packages của bạn.

Giả sử kết quả mong muốn là làm cho mã hoạt động 'ra khỏi hộp', điều này sẽ hoạt động, nhưng chỉ cho tất cả người dùng trên một hệ thống.

Nếu bạn cần nó để làm việc trên nhiều hệ thống, thì bạn phải áp dụng các thay đổi tương tự cho tất cả các hệ thống.

Để triển khai, đây không phải là vấn đề lớn. Thật vậy, nhiều gói Python đã làm một cái gì đó như thế này. ví dụ. trên Ubuntu ...

~$ dpkg -L python-imaging | grep pth 
/usr/share/pyshared/PIL.pth 
/usr/lib/python2.7/dist-packages/PIL.pth 

... nhưng nếu mục đích của bạn là để làm cho nó dễ dàng cho nhiều nhà phát triển đồng thời, từng sử dụng hệ thống riêng của họ, bạn có thể được tốt hơn off gắn bó với các tùy chọn hiện tại của thêm một số 'soạn sẵn 'mã cho mọi mô-đun Python được dự định chạy dưới dạng tập lệnh.

Có thể có một tùy chọn khác, nhưng tùy thuộc vào chính xác những gì bạn đang cố gắng đạt được.

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