2010-12-03 18 views
70

Primero que nada: lo siento, sé que ha habido muchas preguntas sobre importaciones relativas, pero no encontré una solución. Si es posible me gustaría usar la siguiente estructura de directorios:empaquetado de pitón para importaciones relativas

myClass/ 
    __init__.py 
    test/ 
     demo.py 
     benchmark.py 
     specs.py 
    src/ 
     __init__.py 
     myClass.py 

Ahora mis preguntas son:

  • ¿Cómo los archivos de prueba desde dentro del paquete importa correctamente myClass.py?

  • ¿Cómo importaría el paquete desde el exterior, suponiendo que tome myClass como submódulo en libs/myClass o incluya/myClass?

Hasta ahora no he podido encontrar una solución elegante para esto. Por lo que entiendo Guido's Decision debería ser posible hacer from ..src import myClass pero esto va a error:

ValueError: Attempted relative import in non-package

que se ve, ya que no trata a myClass como paquetes. Reading the docs:

The __init__.py files are required to make Python treat the directories as containing packages;

Parece que me falta algo que especifica dónde los guiones del paquete son, debo utilizar .pth?

+6

@Brent Newey, sí, tiene razón, las importaciones relativas parecen ser un tema continuo y después de leer bastantes respuestas todavía sentía la necesidad de describir específicamente mi situación. Después de mostrar esto q, en el canal IRC#python, unas cuantas personas recomendaron usar una estructura de directorios plana: "Mucha gente se resiste a la forma en que Python quiere usar directorios y archivos para obtener información semántica del espacio de nombres. Lo mejor es ceder y hacer lo que Python quiere ". http://jcalderone.livejournal.com/39794.html – eerne

+8

¿Alguien podría proporcionar un enlace a algunos paquetes del mundo real, con un diseño de directorio ejemplar o siguiendo algunas convenciones? (idealmente en github) – eerne

+1

¿Hay '__init __. py' en el directorio' test'? 'ValueError: Intento de importación relativa en non-package' podría estar relacionado con él. – jfs

Respuesta

0

Intra-package-references describe cómo myClass de test/*. Para importar el paquete desde el exterior, debe agregar su ruta a la variable de entorno PYTHONPATH antes de ejecutar la aplicación import o a la lista sys.path en el código antes de importarlo.

Por qué from ..src import myClass falla: probablemente, src no es un paquete de Python, no puede importar desde allí. Debe agregarlo a la ruta de Python como se describe arriba.

+0

Las importaciones relativas se realizan todo el tiempo. Muchos paquetes tienen subpaquetes más pequeños con ellos y dependen de las importaciones relativas. el OP no está preguntando cómo hacer referencia a los paquetes externos. Él está preguntando cómo hacer referencia a otro subpaquete dentro de un paquete. – cstrutton

41

ValueError: Attempted relative import in non-package

Significa que intenta utilizar la importación relativa en el módulo que no es el paquete. Su problema con el archivo que tiene esta declaración from ... import, y no el archivo que está tratando de importar.

Por lo tanto, si realiza importaciones relativas en sus pruebas, por ejemplo, debe hacer que sus pruebas formen parte de su paquete. Esto significa

  1. Adición __init__.py para probar/
  2. ejecutarlos desde una secuencia de comandos fuera, como nosetests

Si ejecuta algo tan python myClass/test/demo.py, las importaciones en relación no va a funcionar también ya se está ejecutando el módulo de demostración no como paquete Las importaciones relativas requieren que el módulo que las utiliza se importe solo como módulo de paquete, from myClass.test.demo import blabla, o con importación relativa.

25

Después de horas de buscar anoche ¡encontré la respuesta a las importaciones relativas en Python! O una solución fácil por lo menos. La mejor manera de arreglar esto es hacer que los módulos se llamen desde otro módulo. Así que supongamos que quiere demo.py importar myClass.py en la carpeta MyClass en la raíz de los subpaquetes. Toy necesita tener un archivo que llame a los otros dos.Por lo que veo, el directorio de trabajo siempre se considera principal, por lo que si prueba la importación desde demo.py con el script demo.py, recibirá ese error. Para ilustrar: La jerarquía

carpeta:

myClass/ 
    main.py #arbitrary name, can be anything 
    test/ 
     __init__.py 
     demo.py 
    src/ 
     __init__.py 
     myClass.py 

myClass.py:

def randomMaths(x): 
    a = x * 2 
    y = x * a 
    return y 

demo.py:

from ..src import myClass 

def printer(): 
    print(myClass.randomMaths(42)) 

main.py:

import test.demo 

demo.printer() 

Si ejecuta demo.py en el intérprete, generará un error, pero ejecutar main.py no lo hará. Es un poco intrincado, pero funciona: D

+3

Estoy usando Python 2.7 y solo hice funcionar el código anterior haciendo tres cosas. Primero, en el nivel donde main.py es, agregué un '__init __. Py'. En segundo lugar, cambié demo.printer() a 'test.demo.printer()'. En tercer lugar, cambié el directorio por encima de main.py y ejecuté 'python -m myClass.main'. De lo contrario, esta fue una respuesta muy útil para mí. :) – Paul

Cuestiones relacionadas