Come importare le classi definite in __init__.py


105

Sto cercando di organizzare alcuni moduli per uso personale. Ho qualcosa del genere:

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

In lib/__init__.py, voglio definire alcune classi da utilizzare se importa lib. Tuttavia, non riesco a capirlo senza separare le classi in file e importarle in formato __init__.py.

Piuttosto che dire:

    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

Voglio qualcosa di simile:

    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

È possibile o devo separare la classe in un altro file?

MODIFICARE

OK, se importi lib da un altro script, posso accedere alla classe Helper. Come posso accedere alla classe Helper da settings.py?

L'esempio qui descrive i riferimenti all'interno del pacchetto. Cito "i sottomoduli spesso hanno bisogno di riferirsi tra loro". Nel mio caso, lib.settings.py ha bisogno dell'Helper e lib.foo.someobject ha bisogno dell'accesso a Helper, quindi dove devo definire la classe Helper?


Il tuo ultimo esempio dovrebbe funzionare. Vedi un ImportError? Puoi incollare i dettagli?
Joe Holloway,

Risposte:


81
  1. La lib/directory principale di deve essere in sys.path.

  2. Il tuo " lib/__init__.py" potrebbe assomigliare a questo:

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

Quindi il seguente esempio dovrebbe funzionare:

from lib.settings import Values
from lib import Helper

Rispondi alla versione modificata della domanda:

__init__.pydefinisce come appare il tuo pacchetto dall'esterno. Se è necessario utilizzare Helperin, settings.pydefinire Helperin un file diverso, ad esempio, " lib/helper.py".

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

2 directory, 6 file

Il comando:

$ python import_submodule.py

Produzione:

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

Come posso importare la classe Helper nel file settings.py nel mio esempio?
scottm

Non capisco perché sia ​​circolare. Se settings.py ha bisogno di Helper e dici foo.someobject.py ha bisogno di Helper, dove suggerisci di definirlo?
scottm

wow, la parola "aiutante" inizia davvero a perdere significato in questo esempio. Tuttavia, mi hai mostrato quello che stavo cercando.
scottm

3
votato per "__init__.py definisce l'aspetto del tuo pacchetto dall'esterno".
Petri

19

Se lib/__init__.pydefinisce la classe Helper, in settings.py puoi usare:

from . import Helper

Questo funziona perché. è la directory corrente e funge da sinonimo per il pacchetto lib dal punto di vista del modulo delle impostazioni. Nota che non è necessario esportare Helper tramite __all__.

(Confermato con python 2.7.10, in esecuzione su Windows.)


1
Funziona bene per me, downvoters per favore spiega il tuo dispiacere?
yo

8

Li metti solo in __init__.py.

Quindi con test / classes.py essere:

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

... e test / __ init__.py essendo:

from classes import *

class Helper(object): pass

Puoi importare test e avere accesso ad A, B e Helper

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

Da dove esegui l'importazione?
Aaron Maenpaa

Dì che voglio importare Helper da lib / settings.py?
scottm

1
Quasi sicuramente si tradurrà in un'importazione circolare (le impostazioni importeranno il test e il test importerà le impostazioni) ... che produrrà il NameError che descrivi. Se vuoi degli helper che vengono usati all'interno del pacchetto dovresti definire un modulo interno che il tuo codice usa.
Aaron Maenpaa

1
Gli helper in init .py dovrebbero essere destinati agli utenti esterni per semplificare la tua API.
Aaron Maenpaa

1
Se non fa parte dell'API, allora init .py non è davvero il posto giusto. lib / internal.py o simili sarebbe molto meglio (che ha il doppio scopo di ridurre la probabilità di importazioni circolari).
Aaron Maenpaa

5

Aggiungi qualcosa di simile a lib/__init__.py

from .helperclass import Helper

ora puoi importarlo direttamente:

from lib import Helper


4

Modifica, dal momento che ho frainteso la domanda:

Metti semplicemente Helperdentro la classe __init__.py. Quello è perfettamente pitonico. Sembra strano provenire da linguaggi come Java.


Hai frainteso. Voglio eliminare il file helperClass.py se possibile.
scottm

Richard non è l'unico che ha frainteso. Il tuo esempio dovrebbe funzionare. Qual è il traceback?
Troy J. Farrell

Bene, allora ho letto correttamente i documenti. Quindi, ora ho appena creato un test case e funziona bene.
scottm

Ho la stessa configurazione nel mio pacchetto, ma ricevo un ImportError "impossibile importare il nome Helper"
scottm

Penso che il mio problema sia che sto cercando di importare la classe Helper da settings.py, come potrei farlo?
scottm

2

Sì, è possibile. Potresti anche voler definire __all__in __init__.pyfiles. È un elenco di moduli che verranno importati quando lo fai

from lib import *

-6

Forse questo potrebbe funzionare:

import __init__ as lib
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.