Cómo lograr una importación relativa en Python

stuff/ __init__.py mylib.py Foo/ __init__.py main.py foo/ __init__.py script.py 

script.py quiere importar mylib.py

Esto es solo un ejemplo, pero realmente solo quiero hacer una importación relativa de un módulo en un directorio principal. He intentado varias cosas y obtuve este error …

Attempted relative import beyond toplevel package

Leí en alguna parte que la secuencia de comandos desde donde se inicia el progtwig no debería estar en el paquete, e intenté modificar la estructura para eso así …

 stuff/ mylib.py foo.py // equivalent of main.py in above foo/ __init__.py script.py 

pero tiene el mismo error.

    ¿Cómo puedo lograr esto? ¿Es esto incluso un enfoque adecuado?

    Edición: En Python 2

    Después de jugar un poco más con él, me di cuenta de cómo configurarlo, y por razones de especificidad no usaré nombres de barras de foo. El directorio de mi proyecto está configurado como …

     tools/ core/ object_editor/ # files that need to use ntlib.py editor.py # see example at bottom __init__.py state_editor/ # files that need to use ntlib.py __init__.py ntlib.py __init__.py # core is the top level package LICENSE state_editor.py # equivalent to main.py for the state editor object_editor.py # equivalent to main.py for the object editor 

    Una línea en object_editor.py parece a …

     from core.object_editor import editor 

    Una línea en editor.py parece a …

     from .. import ntlib 

    o alternativamente

     from core import ntlib 

    La clave es que en el ejemplo que di en la pregunta, el script “principal” se ejecutaba desde el paquete. Una vez que lo moví, creé un paquete específico ( core ), y moví la biblioteca que quería que los editores compartieran ( ntlib ) en ese paquete, todo era Hunky-Dory.

    aunque mientras “cosas” no estén en tu Python PATH, no tienes más remedio que agregar el camino.

    Si conoce el nivel de su script.py de cosas que puede hacer, por ejemplo:

     import sys import os sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..')) 

    Estoy ejecutando Python 3.4.2 en Windows 7 y arranqué mi cabello por esto.

    Al ejecutar cualquiera de estos:

    python -m unittest python -m unittest descubrir

    … Obtendría el error ‘Intenté la importación relativa más allá del paquete de nivel superior’.

    Para mí, la solución fue soltar “..” en mi [test_stock.py]. La línea era: a partir de … stock de stock de importación

    Se cambió a: desde stock importación Stock

    .. y funciona.

    Estructura de la carpeta:

     C:\ | +-- stock_alerter | +-- __init__.py +-- stock.py | \-- tests | +-- __init__.py \-- test_stock.py 

    import ..foo..stuff.mylib debería estar bien

    EDIT quitó la extensión

    Desde el PEP parece que no puede usar una importación relativa para importar un archivo que no está empaquetado.

    Por lo tanto, deberá agregar un __init__.py a las cosas y cambiar sus importaciones a algo así como from .mylib import *

    Sin embargo, el PEP parece no permitir que mylib esté empaquetado en un módulo. Por lo tanto, es posible que deba cambiar la forma en que llama a las funciones de la biblioteca.

    Otra alternativa es mover mylib a un subpaquete e importarlo from .libpackage import mylib

    Si estás en Linux o quizás un * nix similar, puedes piratear esto con enlaces simbólicos.

     stuff/ mylib.py foo.py // equivalent of main.py in above foo/ script.py mylib.py -> ../mylib.py foo2/ script2.py mylib.py -> ../mylib.py 

    Es probable que este no sea un buen patrón a seguir.

    En mi caso, opté por él porque tenía múltiples ejecutables que dependían de la misma biblioteca que se necesitaba colocar en directorios separados.

    La implementación de nuevas pruebas ejecutables no debe requerir que el escritor de pruebas tenga un conocimiento profundo de las importaciones de python.

     tests/ common/ commonlib.py test1/ executable1.py executable2.py commonlib.py -> ../common/commonlib.py test2/ executable1.py executable2.py commonlib.py -> ../common/commonlib.py