2012-04-21 7 views
5

Escribo un paquete P. En la raíz de P hay un módulo m0. En algún lugar dentro P existen módulos M1, M2, ... esa necesidad de importar desde M0La mejor manera de importar el módulo python en la raíz de una jerarquía de paquetes desde otro módulo en el mismo paquete

Por supuesto que puedo escribir en cada uno de estos módulos:

from P.m0 import ... 

Sin embargo, si se cambia el nombre de PI tiene que volver a visitar todos los lugares y volver a escribir tales declaraciones.

También podría usar importaciones relativas pero si muevo un módulo a un nivel diferente en la jerarquía del paquete tengo que ir a arreglar el número de puntos.

También hay otras razones, pero lo que quiero decir es importar del módulo m0 que se encuentra en la raíz de mi paquete, ¿cuál es la mejor manera de expresar esto?

+0

Sin escribir un truco muy introspectivo como 'import x' que cambia' sys.path', o anulando la semántica de 'builtin .__ import__' o creando ganchos de importación como se sugiere en http://docs.python.org/library/functions.html#__import__, está buscando una característica muy razonable que no existe en la mayoría de los idiomas que conozco a partir de 2012. En mi humilde opinión, Python es más adecuado que algunos otros idiomas, pero todavía particularmente inadecuado para las importaciones no detalladas. La visión "pythonic" de que tal verbosidad es explícita y, por lo tanto, buena, probablemente no hará que la característica sea próxima. – ninjagecko

+0

Sabía que me gustaría saber cuál es el problema con esto, de todos modos está haciendo una refactorización importante. El código de escritura es una refactorización importante todo el tiempo. Trabaja con varios paquetes, coloca algo en un lugar, luego se da cuenta de que es una funcionalidad importante que podría usarse en otro lugar, por lo que la refactoriza en otro paquete. Hay algunas cosas de las que debes preocuparte cuando cambias las cosas. Estoy tratando de minimizar la sobrecarga. Por cierto, tengo un m0 en la parte superior de cada paquete, por lo que cuando un módulo se mueve a otro paquete y todavía se refiere al m0 en la parte superior del primer paquete, es propenso a errores. – gae123

+0

Sí, estoy de acuerdo. Sin embargo, no estoy seguro de por qué estás diciendo lo que estás diciendo. No estaba preguntando "¿cuál es el problema?" – ninjagecko

Respuesta

1

Eso no es posible.

Sin embargo, si realiza una refactorización importante en la que mueva los módulos entre subpaquetes y tenga que actualizar algunas importaciones relativas no es un gran problema.

Lo mismo se aplica para renombrar el nombre del paquete de nivel superior si no utiliza importaciones relativas, lo que incluso podría hacerse realmente rápido con la búsqueda y reemplazo de todos sus archivos.

+0

De acuerdo, "importar" es lo suficientemente complicado sin agregar magia extra para arreglar un caso de uso que puede ser manejado mediante una búsqueda y reemplazo rápidos. – katrielalex

0

Si está dispuesto a modificar su pregunta un poco, puede salirse con la suya.

SI los únicos puntos de entrada a su paquete están controlados; p.ej. sólo se prueba su código haciendo algo como invocando testsuite package/.../module.py que será

entonces usted puede asegurarse de que el primero que se hace es import firstthing, y en el paquete/firstthing.py tiene:

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

La principal Es una advertencia que no podrá ejecutar archivos Python sin pasar por sus puntos de entrada. Siempre quiero hacer esto para cada proyecto que escribo en python (para hacer que las importaciones relativas funcionen bien), pero personalmente me parece tan inconveniente que simplemente me rindo.


También hay una segunda alternativa. No es que no es razonable especificar que su paquete requiere otro paquete en la ruta de Python. Este paquete podría ser un paquete de utilidad que realiza un hack importante. Por ejemplo, si el nombre del paquete era "x", podría hacer import x, que usaría el módulo de inspección para realizar una reflexión sobre la pila del intérprete, lo que le permite determinar de qué módulo lo estaba importando. Luego, podría hacer una especie de "retroceder os.walk" yendo por los directorios principales hasta que encuentre la raíz de su paquete (verificando algún archivo indicador especial, o manifiesto, o algo). Luego, el código realizaría programáticamente la modificación anterior de la ruta de Python a través del sys.path. Es lo mismo que el anterior, pero usted tiene la libertad de hacer cosas como ejecutar cualquier archivo de Python sin tener que pasar por un punto de entrada horrible.

Si tiene un control extremo sobre el entorno del shell, también puede simplemente aumentar $ PYTHONPATH para incluir su directorio de paquetes, pero esto es extremadamente frágil en muchos sentidos, y bastante poco elegante.

Cuestiones relacionadas