2009-08-27 27 views
9

Ok, tôi nghĩ rằng bất cứ điều gì tôi làm sai, nó có thể là hiển nhiên rõ ràng, nhưng tôi không thể tìm ra. Tôi đã đọc và đọc lại phần hướng dẫn về các gói và điều duy nhất tôi có thể hình dung là điều này sẽ không hoạt động vì tôi đang thực hiện nó trực tiếp. Đây là thiết lập thư mục:Gói Python?

eulerproject/ 
    __init__.py 
    euler1.py 
    euler2.py 
    ... 
    eulern.py 
    tests/ 
    __init__.py 
    testeulern.py 

Dưới đây là nội dung của testeuler12.py (module thử nghiệm đầu tiên tôi đã viết):

import unittest 
from .. import euler12 

class Euler12UnitTests(unittest.TestCase): 


    def testtriangle(self): 
     """ 
     Ensure that the triangle number generator returns the first 10 
     triangle numbers. 

     """ 
     self.seq = [1,3,6,10,15,21,28,36,45,55] 
     self.generator = euler12.trianglegenerator() 
     self.results = [] 
     while len(self.results) != 10: 
      self.results.append(self.generator.next()) 
     self.assertEqual(self.seq, self.results) 

    def testdivisors(self): 
     """ 
     Ensure that the divisors function can properly factor the number 28. 

     """ 
     self.number = 28 
     self.answer = [1,2,4,7,14,28] 
     self.assertEqual(self.answer, euler12.divisors(self.number)) 


if __name__ == '__main__': 

    unittest.main() 

Bây giờ, khi tôi thực hiện điều này từ IDLE và từ lệnh dòng thời gian trong thư mục, tôi nhận được lỗi sau:

Traceback (most recent call last): 
    File "C:\Documents and Settings\jbennet\My Documents\Python\eulerproject\tests\testeuler12.py", line 2, in <module> 
    from .. import euler12 
ValueError: Attempted relative import in non-package 

tôi nghĩ vấn đề là kể từ khi tôi đang chạy nó trực tiếp, tôi không thể làm hàng nhập khẩu tương đối (vì __name__ thay đổi, và mơ hồ của tôi sự hiểu biết về các mô tả gói là __name__ là một phần của nó như thế nào nói nó gói trong), nhưng trong trường hợp đó những gì bạn guys đề nghị cho làm thế nào để nhập khẩu 'sản xuất' mã được lưu trữ 1 cấp lên từ mã kiểm tra?

+0

Chỉ cần chọn và nhấp vào nút mẫu mã. Hoặc quấn nó trong '' –

Trả lời

8

Nói chung bạn sẽ có một thư mục, tên trong số đó là tên gói của bạn, ở đâu đó trên PYTHONPATH của bạn. Ví dụ:

eulerproject/ 
    euler/ 
     __init__.py 
     euler1.py 
     ... 
     tests/ 
      ... 
    setup.py 

Sau đó, bạn có thể cài đặt toàn hệ thống này, hoặc chắc chắn để thiết lập PYTHONPATH=/path/to/eulerproject/:$PYTHONPATH khi gọi kịch bản của bạn.

Một nhập khẩu tuyệt đối như thế này sau đó sẽ làm việc:

from euler import euler1 

Sửa:

Theo các tài liệu Python, "module kế để sử dụng như các mô-đun chính của một ứng dụng Python nên luôn luôn sử dụng nhập khẩu tuyệt đối. " (Cite)

Vì vậy, kiểm tra khai thác như nose, được đề cập bởi câu trả lời khác, hoạt động vì nó nhập gói thay vì chạy chúng từ dòng lệnh.

Nếu bạn muốn làm những việc bằng tay, kịch bản Runnable của bạn cần phải được bên ngoài hệ thống phân cấp gói, như thế này:

eulerproject/ 
    runtests.py 
    euler/ 
     __init__.py 
     euler1.py 
     ... 
     tests/ 
      __init__.py 
      testeulern.py 

Bây giờ, runtests.py thể làm from euler.tests.testeulern import TestCasetesteulern.py thể làm from .. import euler1

+2

Vâng, nhưng sau đó dự án của bạn không tận dụng lợi thế của nhập khẩu tương đối nữa. Điều tốt đẹp về nhập khẩu tương đối là nó làm cho gói của bạn tự chứa.Nó không phụ thuộc vào tên thư mục chính của nó và nó không thể nhập sai một đơn vị từ, ví dụ, một phiên bản lỗi thời của gói, được chôn cất ở đâu đó trong PYTHONPATH. –

+0

Ok, vậy làm cách nào tôi đặt PYTHONPATH trước khi gọi tập lệnh? Giống như nếu tôi muốn có thể chạy điều này từ hai vị trí khác nhau trên cùng một máy tính? ps: Tôi cũng đang học cách xử lý nhân bản/sáp nhập với mercurial, đó là lý do tại sao nó ở hai nơi. – Jonathanb

+0

Đã thêm ghi chú về cách nhập tương đối có thể hoạt động nếu mô-đun được nhập từ một tập lệnh nằm bên ngoài phân cấp gói. Nếu không, hãy sử dụng dây nịt thử. Đặt biến môi trường tùy thuộc vào những gì bạn đang làm việc. Nếu bạn đang sử dụng bash, chỉ cần thực hiện PYTHONPATH = foo python scriptname.py –

10

Tôi đã gặp vấn đề tương tự. Bây giờ tôi sử dụng nose để chạy thử nghiệm của mình và nhập tương đối được xử lý chính xác.

Vâng, toàn bộ điều nhập tương đối này gây nhầm lẫn.

+2

Tôi chấp nhận câu trả lời khác chỉ vì nó cho phép tôi làm những gì tôi đã cố gắng để làm với nhập khẩu tương đối. Tuy nhiên, tôi cũng đang tải xuống mũi để sử dụng làm bộ phận thử nghiệm vì nó trông mạnh mẽ hơn bất cứ thứ gì tôi có thể tự mình kết hợp với nhau. – Jonathanb

+0

chỉ là những gì tôi đang tìm kiếm, cảm ơn – Copperfield