Câu hỏi Cách nhập các lớp được định nghĩa trong __init__.py


Tôi đang cố gắng tổ chức một số mô-đun để sử dụng riêng của tôi. 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 được sử dụng nếu tôi nhập lib. Tuy nhiên, tôi không thể hình dung ra nó mà 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ó thể, hoặc tôi phải tách lớp thành một tệp khác?

CHỈNH SỬA

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

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


76
2018-02-24 17:35


gốc


Ví dụ cuối cùng của bạn sẽ hoạt động. Bạn đang nhìn thấy một ImportError? Bạn có thể dán các chi tiết? - Joe Holloway


Các câu trả lời:


  1. 'lib/Thư mục chính của phụ huynh phải nằm trong sys.path.

  2. Của bạn 'lib/__init__.py'có thể trông như thế này:

    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

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

__init__.py xác định gói của bạn trông như thế nào từ bên ngoài. Nếu bạn cần sử dụng Helper trong settings.py sau đó xác định Helper trong 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

59
2018-02-24 18:52



Làm thế nào tôi có thể nhập khẩu lớp Helper trong tập tin settings.py trong ví dụ của tôi? - scottm
Tôi không hiểu tại sao đó là thông tư. Nếu settings.py cần Trình trợ giúp và nói foo.someobject.py cần Trình trợ giúp, bạn đề xuất tôi xác định trình duyệt ở đâu? - scottm
wow, từ "helper" thực sự bắt đầu mất ý nghĩa trong ví dụ đó. Tuy nhiên, bạn đã cho tôi thấy những gì tôi đang tìm kiếm. - scottm
@ J.F. Sebastian +1 - Aaron Maenpaa
upvoted cho "__init__.py định nghĩa gói của bạn trông như thế nào từ bên ngoài." - Petri


Nếu lib/__init__.py định nghĩa lớp trình trợ giúp sau đó trong settings.py bạn có thể sử dụng:

from . import Helper

Điều này làm việc vì. là thư mục hiện hành và hoạt động như một từ đồng nghĩa cho gói lib từ quan điểm của mô-đun cài đặt. Lưu ý rằng không cần phải xuất Trình trợ giúp qua __all__.

(Được xác nhận bằng python 2.7.10, chạy trên Windows.)


8
2018-06-30 14:27



Điều này làm việc tốt cho tôi, downvoters xin vui lòng giải thích sự không hài lòng của bạn? - yoyo


Bạn chỉ cần đặt chúng trong __init__.py.

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

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

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

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à Trình trợ giúp

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

7
2018-02-24 17:42



Điều đó không hiệu quả. Tôi nhận được một NameError. - scottm
Bạn đang nhập từ đâu? - Aaron Maenpaa
Điều đó gần như chắc chắn sẽ dẫn đến việc nhập khẩu vòng tròn (cài đặt sẽ nhập kiểm tra và kiểm tra sẽ nhập các thiết lập) ... sẽ tạo ra NameError mà bạn mô tả. Nếu bạn muốn người trợ giúp được sử dụng bên trong gói, bạn nên định nghĩa một mô-đun nội bộ mà mã của bạn sử dụng. - Aaron Maenpaa
Người trợ giúp trong đó.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
Nếu đó không phải là một phần của API, thì trong đó.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 vòng tròn). - Aaron Maenpaa


Chỉnh sửa, kể từ khi tôi hiểu lầm câu hỏi:

Chỉ cần đặt Helper lớp trong __init__.py. Thats hoàn hảo pythonic. Nó chỉ cảm thấy lạ đến từ các ngôn ngữ như Java.


4
2018-02-24 17:42



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 nhầm. Ví dụ của bạn sẽ hoạt động. Traceback là gì? - Troy J. Farrell
Vâng, sau đó tôi đọc các tài liệu một cách chính xác. Vì vậy, bây giờ tôi chỉ cần thực hiện một trường hợp thử nghiệm và nó hoạt động tốt. - scottm
Tôi có cùng một thiết lập trong gói của tôi, nhưng tôi nhận được một ImportError "không thể nhập khẩu Helper tên" - scottm
Tôi nghĩ rằng vấn đề của tôi là tôi đang cố gắng để nhập khẩu lớp Helper từ settings.py, làm thế nào tôi có thể làm điều đó? - scottm


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

from .helperclass import Helper

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

from lib import Helper


3
2018-06-03 09:39





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

from lib import *

1
2018-02-24 17:49





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

import __init__ as lib

-5
2018-01-04 15:09