2011-03-04 31 views
8

Tôi có một số vấn đề trong việc cấu trúc dự án python của tôi. Hiện tại nó là một loạt các tập tin trong cùng một thư mục. Tôi đã cố gắng cấu trúc nó nhưThử nghiệm và cấu trúc gói python

proj/ 
    __init__.py 
    foo.py 
    ... 
    bar/ 
    __init__.py 
    foobar.py 
    ... 
    tests/ 
    foo_test.py 
    foobar_test.py 
    ... 

Vấn đề là tôi không thể, từ thư mục bên trong, nhập mô-đun từ các thư mục bên ngoài. Điều này đặc biệt gây phiền nhiễu với các xét nghiệm.

Tôi đã đọc PEP 328 về nhập tương đối và PEP 366 về nhập tương đối từ mô-đun chính. Nhưng cả hai phương pháp này đều yêu cầu gói cơ bản nằm trong PYTHONPATH của tôi. Trên thực tế tôi có được các lỗi sau

ValueError: Attempted relative import in non-package.

Vì vậy, tôi đã thêm mã boilerplate sau trên đầu trang của các tập tin thử nghiệm

import os, sys 
sys.path.append(os.path.join(os.getcwd(), os.path.pardir)) 

Tôi vẫn nhận được lỗi tương tự. cách chính xác để

  • cấu trúc một gói là gì, hoàn chỉnh với các bài kiểm tra, và
  • thêm thư mục cơ sở để con đường để cho phép nhập khẩu?

EDIT Theo yêu cầu trong các bình luận, tôi thêm một khẩu dụ thất bại (trong file foo_test.py)

import os, sys 
sys.path.append(os.path.join(os.getcwd(), os.path.pardir)) 
from ..foo import Foo 
+0

Bạn có thể hiển thị quá trình nhập mẫu không thành công không? –

+0

Ngoài ra, vui lòng bao gồm giá trị cho 'PYTHONPATH' –

+0

' echo $ PYTHONPATH' của bạn chỉ còn trống. – Andrea

Trả lời

12

Khi bạn sử dụng công tắc -m để chạy mã, thư mục hiện tại sẽ được thêm vào sys.path. Vì vậy, cách đơn giản nhất để chạy thử nghiệm của bạn là từ thư mục cha của proj, sử dụng lệnh:

python -m proj.tests.foo_test 

Để thực hiện công việc đó, bạn sẽ cần phải bao gồm một tập tin __init__.py trong thư mục kiểm tra của bạn để kiểm tra là đúng được công nhận là một phần của gói.

+0

Cảm ơn bạn! Vì vậy, những gì tôi đã mất là 'kiểm thử' chính nó nên là một gói. Đó là một sai lầm khá ngu ngốc, nhưng tôi không thể tìm ra nó. – Andrea

5

Tôi muốn nhập khẩu các module sử dụng đầy đủ proj.NAME gói tiền tố bất cứ khi nào có thể. Đây là phương pháp tiếp cận của Google Python styleguide đề xuất.

Một tùy chọn để cho phép bạn giữ cấu trúc gói, sử dụng đường dẫn gói đầy đủ và vẫn tiếp tục phát triển sẽ sử dụng virtualenv và đặt dự án của bạn ở chế độ phát triển. Dự án của bạn setup.py sẽ cần phải sử dụng setuptools thay vì distutils để nhận lệnh develop.

này sẽ cho phép bạn tránh được những thứ sys.path.append trên:

% virtualenv ~/virt 
% . ~/virt/bin/activate 
(virt)~% cd ~/myproject 
(virt)~/myproject% python setup.py develop 
(virt)~/myproject% python tests/foo_test.py 

đâu foo_test.py sử dụng:

from proj.foo import Foo 

Bây giờ khi bạn chạy python từ bên trong PYTHONPATH bạn virtualenv của bạn sẽ trỏ đến tất cả các gói trong dự án của bạn. Bạn có thể tạo bí danh vỏ ngắn hơn để nhập virtualenv của mình mà không cần phải nhập . ~/virt/bin/activate mỗi lần.

+0

Có vẻ thú vị. Tôi sẽ phải điều tra công cụ virtualenv này. Liệu nó có cho phép tôi làm việc trong một môi trường ảo mà tôi có thể truy cập vào thư mục hiện tại như một gói không? Hay đơn giản là một công cụ với phân phối python bị cô lập - giống như một chroot - nơi tôi phải cài đặt gói của mình mỗi lần trước khi sử dụng nó? – Andrea

+0

Đó là cách nhanh chóng để tạo môi trường Python riêng biệt mà bạn có thể thổi bay và tạo lại nhanh chóng. Tốt cho việc thử các mô-đun bằng pip/easy_install mà không làm ô nhiễm hệ thống Python của bạn. Kịch bản virtualenv 'activate' chèn thư mục' ~/virt/bin' vào mặt trước của 'PATH' để tìm' ~/virt/bin/python' trước trán hệ thống. Lệnh 'develop' liên kết các gói dự án của bạn với' ~/virt/lib/pythonx.x/site-packages' bằng tệp '.pth'. Nó cũng sửa đổi dấu nhắc 'PS1' để cho bạn biết bạn đang" bên trong "virtualenv. – samplebias

+0

Lời khuyên tốt, mặc dù những ngày này bạn có thể muốn chọn 'phân phối' như là một lựa chọn được duy trì tích cực hơn cho' setuptools'. – ncoghlan

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