2013-03-20 4 views
6

Si consideri il seguente scenario:Come posso impedire agli utenti di importare x da un modulo quando esposto nel genitore utilizzando __all__

  • Si dispone di un modulo di M definito m.py contenente una funzione f.

    può essere chiamato in questo modo:

    import M; 
    M.f() 
    
  • Il modulo cresce a una dimensione in cui non è pratico di avere in un unico file. Di dividere M fino in sottomoduli M.X, M.Y, M.Z e mettere quanto segue in M/__init__.py:

    from .X import * 
    from .Y import * 
    from .Z import * 
    
    __all__ = ["f"] 
    

    Il codice originale funziona ancora:

    import M; 
    M.f() 
    

Tuttavia, i nuovi consumatori del codice potrebbe erroneamente accedere direttamente al sottomodulo:

import M.X; 
M.X.f() 

Vorrei impedire questo, in modo tale che tutto il codice rimandi sempre direttamente a M, e non a nessuno dei sottomoduli.

I sottomoduli sono a vantaggio dell'organizzazione interna del codice e il riferimento a M lascia la possibilità di una facile riorganizzazione in futuro.

Un'opzione sarebbe nominare i sottomoduli _X, _Y e _Z per comunicare che sono interni. È l'approccio consigliato?

+4

Non è così. Perchè questo è un problema? Il tuo modulo funziona ancora, il codice che usa quegli elementi funziona ancora. –

+0

Vorrei evitare questo, in modo tale che tutto il codice sia sempre rivolto direttamente a M, e non a nessuno dei sottomoduli. I sottomoduli sono a vantaggio dell'organizzazione interna del codice e il riferimento a M lascia la possibilità di una facile riorganizzazione in futuro. (Domanda modificata per includere questo dettaglio.) –

+3

documenta il modo giusto per farlo e fidati che il tuo utente sarà abbastanza intelligente da seguire i tuoi consigli –

risposta

1

Un'opzione sarebbe nominare i sottomoduli _X, _Y e _Z per comunicare che sono interni. È l'approccio consigliato?

Come non si desidera che le persone accedano a M.X, sarà necessario spostare il modulo X.py in modo che non sia più disponibile come M.X. Potresti cancellarlo come suggerisce Kaie, ma ugh. Quindi sì, il tuo suggerimento è l'approccio raccomandato.

  1. Sposta M/X.py al M/_X.py

  2. Nel M/__init__.py avere la linea from ._X import f

Come altri hanno suggerito, non dovrebbe davvero essere un problema che le persone possono accedere al codice ed è abitudini di programmazione in una lingua con incapsulamento più forte che filtra nei tuoi progetti Python.

I sottomoduli sono a vantaggio dell'organizzazione interna del codice e il riferimento a M lascia la possibilità di una facile riorganizzazione in futuro.

Sì questa è una preoccupazione che ho avuto quando venivo da C e C++ e si occupava di ABI tutto il giorno. Ma spesso non è un problema se il codice è piccolo e ben testato. E questo è il genere di cose che puoi risolvere in modo banale in seguito. Se un giorno decidessi di riorganizzare il codice per avere X come _X allora sono sicuro che Jenkins può dirti cos'altro deve essere aggiornato. :)

0

C'è una via, ma io non credo che tu ti piacera ':

# M/__init__.py 

from .X import * 
del X 
__all__ = ["x"] 

si può ancora fare import M.X, ma getteranno errore quando lo si utilizza.