Как импортировать классы, определенные в __init__.py


105

Я пытаюсь организовать некоторые модули для собственного использования. У меня примерно так:

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

В lib/__init__.py, я хочу определить некоторые классы, которые будут использоваться, если я импортирую lib. Однако я не могу понять это, не разделив классы на файлы и не импортируя их в __init__.py.

Вместо того, чтобы сказать:

    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

Я хочу что-то вроде этого:

    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

Возможно ли это, или мне нужно разделить класс в другой файл?

РЕДАКТИРОВАТЬ

Хорошо, если я импортирую lib из другого скрипта, я могу получить доступ к классу Helper. Как я могу получить доступ к классу Helper из settings.py?

Пример здесь описывает внутрипакетные ссылки. Цитирую «субмодули часто должны ссылаться друг на друга». В моем случае lib.settings.py нужен Helper, а lib.foo.someobject нужен доступ к Helper, так где мне определить класс Helper?


Ваш последний пример должен работать. Вы видите ошибку ImportError? Можете вставить детали?
Джо Холлоуэй,

Ответы:


81
  1. ' lib/«S родительский каталог должен быть sys.path.

  2. Ваш ' lib/__init__.py' может выглядеть так:

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

Тогда должен работать следующий пример:

from lib.settings import Values
from lib import Helper

Ответ на отредактированный вариант вопроса:

__init__.pyопределяет, как ваш пакет выглядит снаружи. Если вам нужно использовать Helperin, settings.pyопределите Helperв другом файле, например, ' lib/helper.py'.

.
| `- import_submodule.py
    `- lib
    | - __init__.py
    | - фу
    | | - __init__.py
    | `- someobject.py
    | - helper.py
    `- settings.py

2 каталога, 6 файлов

Команда:

$ python import_submodule.py

Вывод:

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

Как я могу импортировать класс Helper в файл settings.py в моем примере?
scottm

Я не понимаю, почему это по кругу. Если settings.py нужен помощник, а foo.someobject.py нужен помощник, где вы предлагаете его определить?
scottm

вау, слово «помощник» действительно начинает терять смысл в этом примере. Однако вы показали мне то, что я искал.
scottm

3
проголосовали за "__init__.py определяет, как ваш пакет выглядит снаружи".
Петри

20

Если lib/__init__.pyопределяет класс Helper, то в settings.py вы можете использовать:

from . import Helper

Это работает, потому что. является текущим каталогом и действует как синоним пакета lib с точки зрения модуля настроек. Обратите внимание, что нет необходимости экспортировать Helper через __all__.

(Подтверждено с помощью python 2.7.10, работающего в Windows.)


1
У меня это работает нормально, голосующие против, пожалуйста, объясните свое недовольство?
yoyo

8

Вы просто помещаете их в __init__.py.

Итак, с test / classes.py:

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

... и test / __ init__.py:

from classes import *

class Helper(object): pass

Вы можете импортировать тест и получить доступ к A, B и Helper

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

Откуда вы импортируете?
Аарон Маенпаа,

Скажем, я хочу импортировать Helper из lib / settings.py?
scottm

1
Это почти наверняка приведет к циклическому импорту (настройки импортируют тест, а тест импортирует настройки) ... который приведет к описанной вами NameError. Если вам нужны помощники, которые используются внутри пакета, вы должны определить внутренний модуль, который использует ваш код.
Аарон Маенпаа,

1
Помощники в init .py должны быть для внешних пользователей, чтобы упростить ваш API.
Аарон Маенпаа,

1
Если это не часть API, то init .py действительно не место для него. lib / internal.py или аналогичный был бы намного лучше (который имеет двойную цель - снизить вероятность циклического импорта).
Аарон Маенпаа,

5

Добавьте что-то подобное в lib/__init__.py

from .helperclass import Helper

теперь вы можете импортировать его напрямую:

from lib import Helper


4

Изменить, так как я неправильно понял вопрос:

Просто введите Helperкласс __init__.py. Совершенно питонический. Это просто странно на таких языках, как Java.


Ты не понял. Я хочу по возможности удалить файл helperClass.py.
scottm

Ричард не единственный, кто неправильно понял. Ваш пример должен работать. Что такое трассировка?
Трой Дж. Фаррелл,

Что ж, тогда я правильно прочитал документацию. Итак, теперь я просто сделал тестовый пример, и он отлично работает.
scottm

У меня такая же установка в моем пакете, но я получаю ошибку ImportError «не могу импортировать имя Helper»
scottm

Я думаю, моя проблема в том, что я пытаюсь импортировать класс Helper из settings.py, как я могу это сделать?
scottm

2

Да, это возможно. Вы также можете определить __all__в __init__.pyфайлах. Это список модулей, которые будут импортированы, когда вы

from lib import *

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.