2012-11-02 30 views
5

Tôi đã theo hệ thống phân cấp dự án:Nhập lớp thư viện trong Python

project_dir 
    lib 
    __init__.py 
    ... 
    some_script.py 
    ... 
    agent 
     __init__.py 
     ... 
     errors.py 
     some_agent_script.py 
     ... 

Có định nghĩa lớp SomeException trong lib/đại lý/erros.py tôi sử dụng đoạn mã sau để nhập khẩu bên trong lib/đại lý/some_agent_script. py:

from errors import SomeException 

Ngoài ra tôi sử dụng đoạn mã sau để nhập khẩu trong lib/some_script.py

from agent.errors import SomeException 
.210

Vấn đề là khi tôi nâng cao một SomeException trong lib/đại lý/some_agent_script.py sau đó lib/some_script.py không thể bắt nó trong một ngoại trừ khối:

try: 
    # Here comes a call to lib/agent/some_agent_script.py function 
    # that raises SomeException 
except SomeException, exc: 
    # Never goes here 
    print(exc) 
except Exception, exc: 
    print(exc.__class__.__name__) # prints "SomeException" 

    # Let's print id's 
    print(id(exc.__class__)) 
    print(id(SomeException)) 
    # They are different! 

    # Let's print modules list 
    pprint.pprint(sys.modules) 

tôi có thể nhìn thấy trong sys.modules rằng erros mô-đun được nhập khẩu hai lần: đầu tiên là với 'agent.errors' chìa khóa và thứ hai là với chính

các mã sau 'lib.agent.errors' đi đúng, nhưng nó không phải là một giải pháp tuyệt đẹp:

agent_errors = sys.modules.get('agent.errors') 
from agent_errors import SomeException 

try: 
    # Here comes a call to lib/agent/some_agent_script.py function 
except SomeException: 
    print('OK') 

Tôi nên làm gì để làm cho mô-đun này không được nhập hai lần?

+0

Phiên bản Python là gì? –

+0

Đó là Python 2.6.6 – fey

+2

Đọc liên quan: [SO câu hỏi] (http://stackoverflow.com/questions/1459236/module-reimported-if-imported-from-different-path), [PEP 395] (http://www.python.org/dev/peps/pep-0395/) –

Trả lời

2

Bạn nên luôn sử dụng hàng nhập đủ điều kiện.

from lib.agent.errors import SomeException 

Làm điều này trong mọi mô-đun sử dụng nó. Sau đó, nó sẽ luôn có cùng tên gói. Bạn có lẽ cũng nên thay đổi tên gói cấp cao nhất. Tên "lib" quá chung chung.

Điều này cũng sẽ giúp bạn tiết kiệm một số cơn đau đầu nếu bạn tình cờ đặt tên mô-đun giống như một cơ sở hoặc "cổ phiếu", mô-đun. Ví dụ: giả sử bạn đã tạo mô-đun lib/agent/socket.py và trong lib/agent/some_agent_script.py bạn đã viết import socket. Bạn sẽ không thực sự nhận được mô-đun của bạn, nhưng một trong những cổ phiếu.

Vì vậy, tốt hơn là nên có thói quen luôn sử dụng tên gói đủ điều kiện, tắt gốc chung nếu bạn có thể.

Cách khác là sử dụng nhập khẩu tuyệt đối.

from __future__ import absolute_import 

import .errors 

Lưu ý dấu chấm đầu. Điều này rõ ràng nhập khẩu từ gói hiện tại. Nó cũng nên khắc phục vấn đề của bạn, nhưng tôi thừa nhận tôi đã không thử nó.

+0

Âm thanh tốt, nhưng lib/agent là một thư viện đang được sử dụng trong một số dự án. Nó không phải là tốt để xác định tên đủ điều kiện ở đó, gây ra trong các tác nhân dự án khác có thể được đặt không có trong mô-đun lib. – fey

+0

@fey Tôi đã cập nhật câu trả lời của mình bằng một phương pháp thay thế. – Keith

+0

Cảm ơn! Đó chỉ là những gì tôi cần! Có một bổ sung: nó là không cần thiết để sử dụng absolute_import trong cả hai mô-đun - đó là nâng cao và xử lý một ngoại lệ. – fey

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