2012-10-11 27 views
9

Tôi đang bối rối bởi cách nhập khẩu vòng tròn được xử lý bằng Python. Tôi đã cố gắng để chưng cất một câu hỏi tối thiểu và tôi không nghĩ rằng biến thể chính xác này đã được hỏi trước đây. Về cơ bản, tôi nhìn thấy một sự khác biệt giữaSự khác biệt giữa "import lib.foo" và "import lib.foo as f" trong Python

import lib.foo 

import lib.foo as f 

khi tôi có một phụ thuộc vòng tròn giữa lib.foolib.bar. Tôi đã mong đợi rằng cả hai sẽ làm việc giống nhau: mô-đun (có thể được khởi tạo một nửa) sẽ được tìm thấy trong sys.modules và được đưa vào không gian tên cục bộ. (Từ thử nghiệm tôi nhận thấy rằng import lib.foo thực sự đặt lib vào không gian tên địa phương -. Okay, với cú pháp mà tôi sẽ làm lib.foo.something anyway)

Tuy nhiên, nếu lib.foo là đã có trong sys.modules, sau đó import lib.foo as f cố gắng truy cập foo như một thuộc tính trên lib và tăng AttributeError. Tại sao hành vi (dường như) phụ thuộc vào sự hiện diện trong sys.modules?

Ngoài ra, hành vi này được ghi lại ở đâu? Tôi không cảm thấy rằng các Python import statement reference giải thích hành vi này, hoặc ít nhất tôi không thể giải nén nó :-)

Tất cả trong tất cả Tôi đang cố gắng thay đổi mã cơ sở để sử dụng kiểu oft recommended nơi bạn nhập mô-đun, không phải biểu tượng trong các mô-đun:

from project.package import moduleA 
from project.package import moduleB 

Nhưng điều đó không thành công khi có nhập khẩu vòng tròn giữa hai mô-đun. Tôi đã mong đợi nó hoạt động miễn là các định nghĩa cấp cao nhất trong hai mô-đun không phụ thuộc vào nhau (ví dụ: không có lớp con trong moduleB với lớp cơ sở trong moduleA).

thử nghiệm kịch bản:

#!/bin/sh 
rm -r lib; mkdir lib 

touch lib/__init__.py 

cat > lib/foo.py <<EOF 
# lib.foo module 
print '{ foo' 
#import lib.bar # works 
import lib.bar as b # also works 
#from lib import bar # also works 
print 'foo }' 
EOF 

cat > lib/bar.py <<EOF 
# lib.bar module 
print '{ bar' 
#import lib.foo # works 
import lib.foo as f # AttributeError: 'module' object has no attribute 'foo' 
#from lib import foo # ImportError: cannot import name foo 
print 'bar }' 
EOF 

python -c 'import lib.foo' 
+0

Liên kết http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Imports#Imports bị hỏng - sẽ rất thú vị khi thêm lại –

Trả lời

6

Khi bạn nói import lib.foo as f những gì bạn đang nói với Python làm là tương đương với import lib.foo; f = lib.foo ở cấp bytecode. Bạn kết thúc với một AttributeError trong vấn đề được hỏi vì lib trong trường hợp này không có foo được đặt làm thuộc tính. Python chưa hoàn tất việc nhập khẩu lib.foo khi nó cố gắng thực hiện nhiệm vụ và do đó chưa đặt thuộc tính trên lib; xem mã nguồn Python 3.3 để nhập, tại đó bạn có thể thấy số module is loaded so với các câu lệnh ở xa ở đâu một số module is set on its parent.

Đây là nơi bạn kết thúc với một số vấn đề nhập vòng tròn. Bạn cần cho phép nhập lib.foo hoàn tất trước khi bạn cố gắng truy cập lib.foo, nếu không thuộc tính trên lib sẽ không tồn tại để mã byte truy cập được truy cập. Đây có thể là lý do tại sao bạn cho rằng bạn không sử dụng bất kỳ định nghĩa cấp cao nào trực tiếp trong mã của bạn nhưng trong thực tế bạn đang thông qua các báo cáo nhập của bạn.

+0

Cảm ơn bạn đã trả lời! Vì vậy, khi tôi nhập 'lib.foo',' lib' được nhập lần đầu và khi 'lib.foo' được nhập, thuộc tính' foo' được đặt trong 'lib'. Đó là lý do tại sao 'lib.foo.something' hoạt động sau: nó tìm thuộc tính' foo' * * trên gói 'lib' - cũng giải thích tại sao' import lib.foo' đặt 'lib' vào vùng tên cục bộ. –

+0

Vâng, đó là tất cả chính xác. –

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