Cách nhập các lớp được xác định trong __init__.py


105

Tôi đang cố gắng tổ chức một số mô-đun để sử dụng cho riêng mình. Tôi có một cái gì đó như thế này:

lib/
  __init__.py
  settings.py
  foo/
    __init__.py
    someobject.py
  bar/
    __init__.py
    somethingelse.py

Trong lib/__init__.py, tôi muốn xác định một số lớp sẽ được sử dụng nếu tôi nhập lib. Tuy nhiên, tôi dường như không thể tìm ra nếu không tách các lớp thành các tệp và nhập chúng vào __init__.py.

Thay vì nói:

    lib/
      __init__.py
      settings.py
      helperclass.py
      foo/
        __init__.py
        someobject.py
      bar/
        __init__.py
        somethingelse.py

from lib.settings import Values
from lib.helperclass import Helper

Tôi muốn một cái gì đó như thế này:

    lib/
      __init__.py  #Helper defined in this file
      settings.py
      foo/
        __init__.py
        someobject.py
      bar/
        __init__.py
        somethingelse.py

from lib.settings import Values
from lib import Helper

Có được không, hay tôi phải tách lớp thành một tệp khác?

BIÊN TẬP

OK, nếu tôi nhập lib từ một tập lệnh khác, tôi có thể truy cập lớp Người trợ giúp. Làm cách nào để truy cập lớp Người trợ giúp từ settings.py?

Ví dụ ở đây mô tả các Tham chiếu Nội bộ. Tôi trích dẫn "các mô-đun con thường cần phải tham chiếu đến nhau". Trong trường hợp của tôi, lib.settings.py cần Người trợ giúp và lib.foo.someobject cần quyền truy cập vào Người trợ giúp, vậy tôi nên xác định lớp Người trợ giúp ở đâu?


Ví dụ cuối cùng của bạn ở đó sẽ hoạt động. Bạn có thấy lỗi ImportError không? Bạn có thể dán các chi tiết?
Joe Holloway

Câu trả lời:


81
  1. ' lib/'S thư mục cha phải sys.path.

  2. '' Của bạn lib/__init__.pycó thể trông giống như sau:

    from . import settings # or just 'import settings' on old Python versions
    class Helper(object):
          pass

Sau đó, ví dụ sau sẽ hoạt động:

from lib.settings import Values
from lib import Helper

Câu trả lời cho phiên bản đã chỉnh sửa của câu hỏi:

__init__.pyxác định cách gói hàng của bạn nhìn từ bên ngoài. Nếu bạn cần sử dụng Helpertrong settings.pythì hãy xác định Helpertrong một tệp khác, ví dụ: ' lib/helper.py'.

.
| `- import_submodule.py
    `- lib
    | - __init__.py
    | - foo
    | | - __init__.py
    | `- someobject.py
    | - helper.py
    `- settings.py

2 thư mục, 6 tệp

Lệnh:

$ python import_submodule.py

Đầu ra:

settings
helper
Helper in lib.settings
someobject
Helper in lib.foo.someobject

# ./import_submodule.py
import fnmatch, os
from lib.settings import Values
from lib import Helper

print
for root, dirs, files in os.walk('.'):
    for f in fnmatch.filter(files, '*.py'):
        print "# %s/%s" % (os.path.basename(root), f)
        print open(os.path.join(root, f)).read()
        print


# lib/helper.py
print 'helper'
class Helper(object):
    def __init__(self, module_name):
        print "Helper in", module_name


# lib/settings.py
print "settings"
import helper

class Values(object):
    pass

helper.Helper(__name__)


# lib/__init__.py
#from __future__ import absolute_import
import settings, foo.someobject, helper

Helper = helper.Helper


# foo/someobject.py
print "someobject"
from .. import helper

helper.Helper(__name__)


# foo/__init__.py
import someobject

Làm cách nào để nhập lớp Người trợ giúp trong tệp settings.py trong ví dụ của tôi?
scottm 24/02/09

Tôi không hiểu tại sao lại là hình tròn. Nếu settings.py cần Người trợ giúp và nói rằng foo.someobject.py cần Người trợ giúp, bạn đề nghị tôi xác định nó ở đâu?
scottm

wow, từ "helper" thực sự bắt đầu mất ý nghĩa trong ví dụ đó. Tuy nhiên, bạn đã chỉ cho tôi những gì tôi đang tìm kiếm.
scottm

3
ủng hộ cho "__init__.py xác định cách gói của bạn nhìn từ bên ngoài."
Petri

19

Nếu lib/__init__.pyxác định lớp Người trợ giúp thì trong settings.py bạn có thể sử dụng:

from . import Helper

Điều này hoạt động bởi vì. là thư mục hiện tại và hoạt động như một từ đồng nghĩa với gói lib theo quan điểm của mô-đun cài đặt. Lưu ý rằng không cần thiết phải xuất Helper qua __all__.

(Đã xác nhận với python 2.7.10, chạy trên Windows.)


1
Điều này đang làm việc tốt cho tôi, những người phản đối xin vui lòng giải thích sự không hài lòng của bạn?
yoyo

8

Bạn chỉ cần đưa chúng vào __init__.py.

Vì vậy, với test / class.py là:

class A(object): pass
class B(object): pass

... và kiểm tra / __ init__.py là:

from classes import *

class Helper(object): pass

Bạn có thể nhập thử nghiệm và có quyền truy cập vào A, B và Người trợ giúp

>>> import test
>>> test.A
<class 'test.classes.A'>
>>> test.B
<class 'test.classes.B'>
>>> test.Helper
<class 'test.Helper'>

Bạn đang nhập hàng từ đâu?
Aaron Maenpaa

Giả sử tôi muốn nhập Trình trợ giúp từ lib / settings.py?
scottm

1
Điều đó gần như chắc chắn sẽ dẫn đến nhập vòng tròn (cài đặt sẽ nhập kiểm tra và kiểm tra sẽ nhập cài đặt) ... sẽ tạo ra NameError mà bạn mô tả. Nếu bạn muốn các trình trợ giúp được sử dụng bên trong gói, bạn nên xác định một mô-đun bên trong mà mã của bạn sử dụng.
Aaron Maenpaa

1
Các trình trợ giúp trong init .py nên dành cho người dùng bên ngoài để đơn giản hóa API của bạn.
Aaron Maenpaa

1
Nếu nó không phải là một phần của API, thì init .py thực sự không phải là nơi dành cho nó. lib / internal.py hoặc tương tự sẽ tốt hơn nhiều (có mục đích kép là giảm khả năng nhập khẩu theo đường vòng).
Aaron Maenpaa

5

Thêm một cái gì đó như thế này vào lib/__init__.py

from .helperclass import Helper

bây giờ bạn có thể nhập trực tiếp:

from lib import Helper


4

Chỉnh sửa, vì tôi đã hiểu sai câu hỏi:

Chỉ cần đưa Helperlớp vào __init__.py. Đó là một con trăn hoàn hảo. Nó chỉ cảm thấy kỳ lạ đến từ các ngôn ngữ như Java.


Bạn đã hiểu lầm. Tôi muốn loại bỏ tệp helperClass.py nếu có thể.
scottm

Richard không phải là người duy nhất hiểu lầm. Ví dụ của bạn sẽ hoạt động. Truy xuất nguồn gốc là gì?
Troy J. Farrell

Vâng, sau đó tôi đọc tài liệu một cách chính xác. Vì vậy, bây giờ tôi chỉ tạo một trường hợp thử nghiệm và nó hoạt động tốt.
scottm 24/02/09

Tôi có cùng một thiết lập trong gói của mình, nhưng tôi nhận được lỗi ImportError "không thể nhập tên Người trợ giúp"
scottm

Tôi nghĩ rằng vấn đề của tôi là tôi đang cố gắng nhập lớp Người trợ giúp từ settings.py, làm cách nào để làm điều đó?
scottm

2

Có, nó là có thể. Bạn cũng có thể muốn xác định __all__trong __init__.pycác tệp. Đó là danh sách các mô-đun sẽ được nhập khi bạn thực hiện

from lib import *

-6

Có thể điều này có thể hoạt động:

import __init__ as lib
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.