2009-08-08 40 views
120

Tôi có hai mô-đun python:AttributeError: 'module' đối tượng không có thuộc tính

a.py

import b 

def hello(): 
    print "hello" 

print "a.py" 
print hello() 
print b.hi() 

b.py

import a 

def hi(): 
    print "hi" 

Khi tôi chạy a.py, tôi nhận được:

AttributeError: 'module' object has no attribute 'hi' 

Những gì doe s lỗi có nghĩa là gì? Làm thế nào để tôi sửa chữa nó?

+12

Đây là một thiết kế khủng khiếp. Tại sao b.py nhập một khi nó không tham chiếu bất kỳ phần nào của a.py? Bạn có hỏi cách khắc phục sự cố này không? http://stackoverflow.com/search?q=%5Bpython%5D+circular+dependency –

+0

Lưu ý rằng câu hỏi của bạn rất giống với câu trả lời này. Rõ ràng các mã trong câu trả lời này hoạt động chỉ tìm thấy, nhưng bạn không? http://stackoverflow.com/a/7336880/565879 – Buttons840

Trả lời

126

Bạn có mức nhập chung nhất ở mức cao nhất, điều này hầu như luôn là ý tưởng tồi.

Nếu bạn thực sự phải có hàng nhập khẩu lẫn nhau trong Python, cách để làm điều đó là để nhập chúng trong một hàm:

# In b.py: 
def cause_a_to_do_something(): 
    import a 
    a.do_something() 

Bây giờ a.py có thể yên tâm làm import b mà không gây ra vấn đề.

(Thoạt nhìn, có vẻ như cause_a_to_do_something() sẽ cực kỳ kém hiệu quả vì mỗi lần bạn gọi nó là import, nhưng thực tế công việc nhập chỉ được thực hiện lần đầu tiên. , đó là một hoạt động nhanh chóng.)

+0

Cảm ơn bạn! Tôi biết lần đầu tiên nhập khẩu ở những nơi khác nhau tạo ra sự khác biệt như vậy. –

+0

Hãy lưu ý rằng điều này cho biết thêm over-head khi chức năng được gọi là, khi bạn đặt logic nhập khẩu tại thời gian gọi hàm, thay vì thời gian tải chương trình. – Rebs

+2

Thú vị; Tôi tự hỏi tại sao thông dịch viên không đưa ra thông báo lỗi thích hợp trong trường hợp này? –

35

Sự cố là phụ thuộc vòng tròn giữa các mô-đun. a nhập bb nhập a. Nhưng một trong số chúng cần phải được tải trước - trong trường hợp này python sẽ kết thúc khởi tạo mô-đun a trước bb.hi() chưa tồn tại khi bạn cố truy cập vào số a.

+0

Cảm ơn bạn! Đó là những gì tôi đoán. Nhưng tôi không thể tìm thấy một số tài liệu đề cập đến nó. Nếu tôi cần hai mô-đun nhập một số thuộc tính từ nhau, tôi nên làm gì? –

+1

@Stephen Hsu: Phá vỡ phụ thuộc vòng tròn rất dễ dàng. Nó đã được yêu cầu trên SO nhiều lần. http://stackoverflow.com/search?q=%5Bpython%5D+circular+dependency –

+0

@ S.Lott: Cảm ơn bạn. Tôi chỉ biết rằng đó là một vấn đề phụ thuộc vòng tròn. –

63

Tôi cũng đã thấy lỗi này khi vô tình đặt tên mô-đun có cùng tên với một trong các mô-đun chuẩn của Python. Ví dụ. Tôi đã có một mô-đun gọi là commands cũng là một mô-đun thư viện Python. Điều này được chứng minh là khó theo dõi khi nó hoạt động chính xác trên môi trường phát triển cục bộ của tôi nhưng không thành công với lỗi được chỉ định khi chạy trên Google App Engine.

+4

đây là câu trả lời giải quyết được vấn đề của tôi. – Tommy

+2

Tôi đã sử dụng 'abc.py' để viết một bài kiểm tra để chứng minh hành vi nhập khẩu trong python, mà cắn tôi rất nhiều ... – Bin

+0

Tôi nghi ngờ điều này và xóa mô-đun .py nhưng quên xóa .pyc mà vẫn gây ra lỗi. – Echelon

14

Tôi đã nhận lỗi này bằng cách tham khảo một enum được nhập khẩu một cách sai lầm, ví dụ:

from package import MyEnumClass 
# ... 
# in some method: 
return MyEnumClass.Member 

nhập đúng:

from package.MyEnumClass import MyEnumClass 

Hy vọng rằng sẽ giúp người

5

tôi có kinh nghiệm này do mô-đun không thực sự được nhập. Mã trông giống như sau:

import a.b, a.c 

# ... 

something(a.b) 
something(a.c) 
something(a.d) # My addition, which failed. 

Dòng cuối cùng dẫn đến AttributeError. Nguyên nhân là do tôi đã không nhận thấy rằng các mô-đun con của a (a.ba.c) là một cách rõ ràng được nhập và giả định rằng tuyên bố import thực sự được nhập a.

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