__İnit__.py'de tanımlanan sınıflar nasıl içe aktarılır


105

Kendi kullanımım için bazı modüller düzenlemeye çalışıyorum. Bende böyle bir şey var:

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

İçinde lib/__init__.py, lib'yi içe aktarırsam kullanılacak bazı sınıfları tanımlamak istiyorum. Ancak, sınıfları dosyalara ayırmadan ve içeri aktarmadan anlayamıyorum __init__.py.

Söylemektense:

    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

Bunun gibi bir şey istiyorum:

    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

Mümkün mü yoksa sınıfı başka bir dosyaya ayırmam gerekiyor mu?

DÜZENLE

Tamam, kütüphaneyi başka bir komut dosyasından içe aktarırsam, Yardımcı sınıfına erişebilirim. Helper sınıfına settings.py'den nasıl erişebilirim?

Örnek burada İçi Paket Referansları açıklanır. "Alt modüllerin genellikle birbirine başvurması gerekir" den alıntı yapıyorum. Benim durumumda, lib.settings.py'nin Yardımcıya ihtiyacı var ve lib.foo.someobject'in Yardımcıya erişmesi gerekiyor, öyleyse Helper sınıfını nerede tanımlamalıyım?


Oradaki son örneğiniz işe yaramalı. Bir ImportError mı görüyorsunuz? Ayrıntıları yapıştırabilir misin?
Joe Holloway

Yanıtlar:


81
  1. ' lib/'Nin üst dizin olmalıdır sys.path.

  2. Sizin ' lib/__init__.py' şuna benzeyebilir:

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

O zaman aşağıdaki örnek çalışmalıdır:

from lib.settings import Values
from lib import Helper

Sorunun düzenlenmiş halini yanıtlayın:

__init__.pypaketinizin dışarıdan nasıl göründüğünü tanımlar. Kullanmak gerekiyorsa Helperiçinde settings.pydaha sonra tanımlamak Helper'farklı bir dosya eg lib/helper.py'.

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

2 dizin, 6 dosya

Komuta:

$ python import_submodule.py

Çıktı:

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

Örneğimdeki settings.py dosyasındaki Yardımcı sınıfı nasıl içe aktarabilirim?
scottm

Bunun neden döngüsel olduğunu anlamıyorum. Settings.py'nin Helper'a ihtiyacı varsa ve foo.someobject.py'nin Helper'a ihtiyacı varsa, onu nerede tanımlamamı önerirsiniz?
scottm

vay, "yardımcı" kelimesi bu örnekte gerçekten anlamını kaybetmeye başlıyor. Ancak, bana aradığımı gösterdin.
scottm

3
"__init__.py, paketinizin dışarıdan nasıl göründüğünü tanımlar." için oy verildi.
Petri

19

Eğer lib/__init__.pyYardımcısı sınıf tanımlayıp sonra settings.py içinde kullanabilirsiniz:

from . import Helper

Bu işe yarıyor çünkü. mevcut dizindir ve ayarlar modülünün bakış açısından lib paketinin eşanlamlısıdır. Helper'ı üzerinden dışa aktarmanın gerekli olmadığını unutmayın __all__.

(Windows'ta çalışan python 2.7.10 ile onaylandı.)


1
Bu benim için iyi çalışıyor, olumsuz oy verenler lütfen memnuniyetsizliğinizi açıklar mısınız?
yoyo

8

Onları __init__.py'ye koyarsınız.

Yani test / classes.py ile:

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

... ve / __ init__.py test edin:

from classes import *

class Helper(object): pass

Testi içe aktarabilir ve A, B ve Yardımcı'ya erişebilirsiniz

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

İthalatı nereden yapıyorsunuz?
Aaron Maenpaa

Helper'ı lib / settings.py'den içe aktarmak istediğimi varsayalım.
scottm

1
Bu neredeyse kesinlikle döngüsel bir içe aktarmayla sonuçlanacaktır (ayarlar testi içe aktaracak ve test ayarları içe aktaracaktır) ... bu da tanımladığınız Ad Hatasını üretecektir. Paketin içinde kullanılan yardımcılar istiyorsanız, kodunuzun kullandığı dahili bir modül tanımlamalısınız.
Aaron Maenpaa

1
Yardımcılar init harici kullanıcıların API basitleştirmek için .py olmalıdır.
Aaron Maenpaa

1
API'nin bir parçası değilse, init .py gerçekten bunun yeri değildir. lib / internal.py veya benzeri çok daha iyi olabilir (bu, döngüsel içe aktarma olasılığını azaltmak gibi iki amaca sahiptir).
Aaron Maenpaa

5

Buna benzer bir şey ekle lib/__init__.py

from .helperclass import Helper

şimdi doğrudan içe aktarabilirsiniz:

from lib import Helper


4

Soruyu yanlış anladığım için düzenleyin:

Sadece Helpersınıfı koyun __init__.py. Bu mükemmel pitonik. Java gibi dillerden gelmek tuhaf geliyor.


Sen yanlış anladın. Mümkünse helperClass.py dosyasını kaldırmak istiyorum.
scottm

Richard yanlış anlayan tek kişi değil. Örneğiniz işe yaramalı. Geri dönüş nedir?
Troy J. Farrell

O zaman belgeleri doğru okudum. Bu yüzden, şimdi sadece bir test çalışması yaptım ve iyi çalışıyor.
scottm

Paketimde de aynı kurulum var, ancak bir ImportError "ad Yardımcısı içe aktarılamıyor" alıyorum
scottm

Sanırım sorunum, Helper sınıfını settings.py'den içeri aktarmaya çalışıyorum, bunu nasıl yapabilirim?
scottm

2

Evet mümkün. Ayrıca tanımlamak isteyebilirsiniz __all__içinde __init__.pydosyalar. Bunu yaptığınızda içe aktarılacak modüllerin listesi

from lib import *

-6

Belki bu işe yarayabilir:

import __init__ as lib
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.