2012-04-21 7 views
5

Scrivo un pacchetto P. Alla radice di P c'è un modulo m0. Da qualche parte dentro P Ci sono moduli m1, m2, ... che hanno bisogno di importare da M0Il modo migliore per importare il modulo python nella radice di una gerarchia di pacchetti da un altro modulo nello stesso pacchetto

Certo che posso scrivere in ognuno di questi moduli:

from P.m0 import ... 

Tuttavia se cambio il nome di PI devono rivisitare tutti i luoghi e riscrivere tali affermazioni.

Potrei anche usare le importazioni relative ma se sposto un modulo a un livello diverso nella gerarchia dei pacchetti devo andare a correggere il numero di punti.

Ci sono anche altri motivi, ma in fondo, voglio davvero dire import dal modulo m0 che si trova nella root del mio pacchetto, qual è il modo migliore per esprimere questo?

+0

A corto di scrivere un hack molto introspettivo come 'import x' che cambia' sys.path', o sovrascrivendo la semantica di 'builtin .__ import__' o creando hook di importazione come suggerito in http://docs.python.org/library/functions.html#__import__, stai cercando una funzionalità molto ragionevole che non esiste nella maggior parte delle lingue che conosco del 2012. A mio modesto parere, python è più adatto di alcuni altri linguaggi, ma ancora particolarmente inadatto per le importazioni non verbose. La visione "pitonica" che tale verbosità è esplicita, e quindi buona, probabilmente non renderà la caratteristica imminente. – ninjagecko

+0

Sapevo che avrei ottenuto quello che è il grosso problema di questo, stai comunque facendo un grande refactoring. Scrivere codice è un importante refactoring per tutto il tempo. Lavorate con diversi pacchetti, mettete qualcosa in un posto, poi vi rendete conto che è una funzionalità importante che potrebbe essere utilizzata altrove, quindi la rifattate in un altro pacchetto. Ci sono molte cose che devi preoccuparti quando muovi le cose Sto cercando di minimizzare il sovraccarico. A proposito, ho un m0 nella parte superiore di ogni pacchetto, quindi quando un modulo si sposta su un altro pacchetto e fa ancora riferimento a m0 nella parte superiore del primo pacchetto, è soggetto ad errori. – gae123

+0

Sì, sono d'accordo. Eppure non sono sicuro del perché tu stia dicendo quello che stai dicendo. Non stavo chiedendo "qual è il grosso problema di questo". – ninjagecko

risposta

1

Questo non è possibile.

Tuttavia, se si esegue un grande refactoring in cui si spostano i moduli tra i pacchetti secondari che devono aggiornare alcune importazioni relative non è un problema enorme.

Lo stesso vale per la ridenominazione del nome del pacchetto di primo livello se non si utilizzano le importazioni relative, operazione che potrebbe anche essere eseguita molto rapidamente con la funzione di ricerca e sostituzione su tutti i file.

+0

Concordato - 'import' è abbastanza complicato senza aggiungere magia extra per risolvere un caso d'uso che può essere gestito da una rapida ricerca e sostituzione. – katrielalex

0

Se sei disposto a modificare la tua domanda un pochino, puoi farla franca.

SE gli unici punti di ingresso per il pacchetto sono controllati; per esempio. si prova solo il codice facendo qualcosa di simile invocando testsuite package/.../module.py che sarà

allora si può fare in modo che la prima cosa da fare è import firstthing, e nel pacchetto/firstthing.py avete:

import sys 
import os.path 
packageDir = os.path.split(__name__)[0] 
sys.path[:] = sys.path+[packageDir] # or maybe you want it first... 

Il principale l'avvertenza è che non sarete in grado di eseguire file python senza passare attraverso i vostri punti di accesso. Voglio sempre farlo per ogni progetto che scrivo in python (per fare in modo che le importazioni relative funzionino bene), ma personalmente trovo questo così scomodo che mi arrendo.


C'è anche una seconda alternativa. Non è che irragionevole specificare che il pacchetto richiede un altro pacchetto nel percorso python. Questo pacchetto potrebbe essere un pacchetto di utilità che esegue un attacco grave. Ad esempio se il nome del pacchetto fosse "x", si potrebbe fare import x che userebbe il modulo inspect per eseguire la riflessione sullo stack dell'interprete, consentendo di capire da quale modulo si stava importando. Quindi si potrebbe fare una sorta di "backwards os.walk" andando su directory madri fino a trovare la radice del pacchetto (controllando la presenza di qualche indicatore speciale, o manifest, o qualcosa del genere). Quindi il codice eseguirà programmaticamente la modifica sopra del percorso Python tramite sys.path. È lo stesso di quanto sopra, ma hai la libertà di fare cose come eseguire qualsiasi file python senza dover passare attraverso un terribile punto di accesso.

Se si dispone di un controllo estremo sull'ambiente di shell, è anche possibile aumentare il $ PYTHONPATH per includere la directory del pacchetto, ma questo è estremamente fragile in molti modi e piuttosto poco elegante.

Problemi correlati