Importazione relativa assoluta vs esplicita del modulo Python


90

Mi chiedo quale sia il modo preferito per importare i pacchetti in un'applicazione Python. Ho una struttura del pacchetto come questa:

project.app1.models
project.app1.views
project.app2.models

project.app1.viewsimportazioni project.app1.modelseproject.app2.models . Ci sono due modi per farlo che mi vengono in mente.

Con importazioni assolute:

import A.A
import A.B.B

o con importazioni relative esplicite, come introdotto in Python 2.5 con PEP 328 :

# explicit relative
from .. import A
from . import B

Qual è il modo più pitonico per farlo?


gli esempi "relativi espliciti" sono errori di sintassi. Le importazioni relative devono essere nella forma from _ import ..., quindi i tuoi esempi sarebbero from .. import Aefrom . import B
MestreLion

@MestreLion Buona cattura, hai perfettamente ragione! Ho aggiornato la mia domanda dal import ..Aal from .. import A. Notevole che ci sono voluti solo 9 anni prima che qualcuno se ne accorgesse;)
Daniel Hepper

Risposte:


56

Importazioni assolute. Da PEP 8:

Le importazioni relative per le importazioni all'interno di un pacchetto sono fortemente scoraggiate. Usa sempre il percorso assoluto del pacchetto per tutte le importazioni. Anche ora che PEP 328 [7] è completamente implementato in Python 2.5, il suo stile di importazioni relative esplicite è attivamente scoraggiato; le importazioni assolute sono più portabili e di solito più leggibili.

Le importazioni relative esplicite sono una bella caratteristica del linguaggio (immagino), ma non sono così esplicite come le importazioni assolute. La forma più leggibile è:

import A.A
import A.B.B

soprattutto se importi diversi spazi dei nomi. Se guardi alcuni progetti / tutorial ben scritti che includono importazioni dall'interno dei pacchetti, di solito seguono questo stile.

Le poche sequenze di tasti in più che prendi per essere più esplicite salveranno gli altri (e forse te) un sacco di tempo in futuro quando cercheranno di capire il tuo spazio dei nomi (specialmente se migra a 3.x, in cui alcuni dei pacchetti i nomi sono cambiati).


@Rafe, "guarda alcuni progetti ben scritti ..." qualche suggerimento?
denis

@Denis: Rietveld è il progetto di Guido van Rossum, quindi immagino che sarebbe un buon posto dove guardare ( code.google.com/p/rietveld ). La libreria standard Python non è così eccezionale, molto di quel codice non segue le convenzioni.
Rafe Kettler

68
@Rafe: quella parte di PEP-8 è obsoleta, secondo Guido. mail.python.org/pipermail/python-dev/2010-October/104476.html
Brandon Rhodes

13
Quella dichiarazione non è più in PEP-8 adesso. Ora afferma che le importazioni assolute sono consigliate, ma le importazioni relative sono un'alternativa accettabile.
dano

6
Il problema che ho con le importazioni assolute è quando utilizzo un pacchetto all'interno di un altro pacchetto. Nel mio caso, è presente come sottomodulo git. In questo caso, anche se posso importare il pacchetto di primo livello, tutti i pacchetti al di sotto di questo non possono essere importati perché non riescono a trovare i propri moduli con importazioni assolute. Mentre se uso le importazioni relative a questo livello inferiore, funziona tutto.
davidA

125

Le importazioni relative di Python non sono più fortemente scoraggiate, ma in questo caso è fortemente consigliato l'uso di absolute_import.

Si prega di vedere questa discussione citando lo stesso Guido:

"Non è per lo più storico? Fino all'implementazione della nuova sintassi di importazione relativa c'erano vari problemi con le importazioni relative. La soluzione a breve termine era raccomandare di non usarli. La soluzione a lungo termine era implementare una sintassi univoca. Ora è ora di ritirare l'anti-raccomandazione. Naturalmente, senza esagerare, trovo ancora un gusto acquisito; ma hanno il loro posto ".

L'OP collega correttamente il PEP 328 che dice:

Sono stati presentati diversi casi d'uso, il più importante dei quali è la possibilità di riorganizzare la struttura di grandi pacchetti senza dover modificare i sotto-pacchetti. Inoltre, un modulo all'interno di un pacchetto non può importare facilmente se stesso senza importazioni relative.

Vedi anche la domanda quasi duplicata Quando o perché usare le importazioni relative in Python

Ovviamente è ancora una questione di gusti. Sebbene sia più facile spostare il codice con le importazioni relative, ciò potrebbe anche interrompere inaspettatamente le cose; e rinominare le importazioni non è così difficile.

Per forzare il nuovo comportamento da PEP 328 utilizzare:

from __future__ import absolute_import

In questo caso, l'importazione relativa implicita non sarà più possibile (es. import localfileNon funzionerà più, solo from . import localfile). Per un comportamento pulito ea prova di futuro, è consigliabile utilizzare absolute_import.

Un avvertimento importante è che a causa di PEP 338 e PEP 366 , le importazioni relative richiedono che il file python venga importato come modulo: non è possibile eseguire un file.py con un'importazione relativa o si otterrà un file ValueError: Attempted relative import in non-package.

Questa limitazione dovrebbe essere presa in considerazione quando si valuta l'approccio migliore. Guido è contro l'esecuzione di script da un modulo in ogni caso:

Sono -1 su questo e su qualsiasi altra proposta di twiddling della macchina __main__. L'unico caso d'uso sembra essere l'esecuzione di script che si trovano all'interno della directory di un modulo, che ho sempre visto come un antipattern. Per farmi cambiare idea dovresti convincermi che non lo è.

Discussioni esaustive sull'argomento possono essere trovate su SO; ri. Python 3 questo è abbastanza completo:


9
Guido l'ha scritto nel 2010 ed è ancora nel PEP? Come possiamo fidarci dei PEP se sono così obsoleti?
Jabba

2
I PEP sono come gli emendamenti degli Stati Uniti nel senso che puoi modificare le cose. Ci sono anche molti PEPS rifiutati. I PEP sono proposte. Possono essere accettati, rifiutati o diventare obsoleti, il che spesso significa nuovo PEP. PEP 8 è una guida di stile in modo che possa essere modificata sul posto.
CppLearner

2
Sono confuso sulla parte "un modulo all'interno di un pacchetto non può importare facilmente se stesso ...". Non avevo mai sentito parlare di moduli che si importano da soli prima.
matiascelasco

2
Un possibile esempio @matiascelasco: se hai foo / bar.py e foo / baz.py ma anche baz.py da qualche altra parte. Se vuoi importare foo.baz da bar potresti voler essere sicuro di cosa stai importando, ad es. import .baz- questa è solo una semplicistica di molte situazioni simili descritte nel PEP.
Stefano

La tua risposta non distingue chiaramente il cambiamento nel consentirli. Le importazioni relative implicite non dovrebbero mai essere utilizzate, ma le importazioni relative esplicite possono essere utilizzate. Parente implicito è stato rimosso da Python3.
ninMonkey

33

Le importazioni relative non solo ti lasciano libero di rinominare il tuo pacchetto in un secondo momento senza modificare dozzine di importazioni interne, ma ho anche avuto successo con loro nel risolvere alcuni problemi che coinvolgono cose come importazioni circolari o pacchetti dello spazio dei nomi, perché non rimandano Python "al top "per avviare nuovamente la ricerca del modulo successivo dallo spazio dei nomi di primo livello.


4
Questo è lo stile sconsigliato secondo la guida allo stile di Python. Offuscano gravemente la leggibilità e non valgono la "comodità" percepita a cui alludi. Se è necessario utilizzare le importazioni relative per risolvere un problema, lo stai facendo in modo sbagliato.
Rafe Kettler

14
Nota il suo commento (Brandon Rhodes) sull'altra risposta, con un link che mostra che non è più scoraggiato.
Jon Coombs

1
@RafeKettler puoi spiegare come useresti le importazioni assolute in un pacchetto che è esso stesso incluso in un altro pacchetto? Le importazioni assolute falliranno all'interno del pacchetto interno perché non conoscono il nuovo livello superiore. Le importazioni relative continuano a funzionare. Si potrebbe probabilmente sostenere che il pacchetto non dovrebbe essere annidato in un altro in primo luogo, ma un po 'di codice è pensato per essere riutilizzabile e questo accade spesso. Un sacco di codice riutilizzato non è impacchettato per il pubblico e quindi non viene fornito come pacchetto separato, quindi vengono utilizzati metodi ad-hoc come l'importazione / sottomoduli VCS
davidA

3
@meowsqueak Sono d'accordo, alcuni pacchetti non sono facilmente installabili (non sono su pip, non vuoi usarli python setup.py installo python setup.py developper qualsiasi motivo), in quei casi forzo il codice sorgente e lo aggiungo come sottomodulo git. Quando questi pacchetti utilizzano importazioni assolute sul proprio nome di pacchetto, le loro importazioni falliscono. L'unica soluzione è utilizzare importazioni relative esplicite. Questo è ciò che dovrebbe essere incoraggiato, credo.
CMCDragonkai
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.