2011-01-31 8 views
7

Estoy buscando una forma de emular los enlaces simbólicos para las importaciones de Python. Me gustaría ser capaz de descomprimir la siguiente estructura de carpetas en el lugar y sin duplicación de archivos:¿Cómo puedo redirigir de forma transparente una importación de Python?

root 
├─ python_lib 
│ └─ my_utils 
│  ├─ __init__.py 
│  └─ etc.py 
├─ app1 
├─ app2 
└─ app3 
    ├─ lib 
    │ ├─ __init__.py 
    │ └─ my_utils.py 
    └─ run.py 

app3/run.py contiene esto:

from lib.my_utils import etc 

etc.pancakes() 

Me gustaría que el código para utilizar el etc situado en python_lib/my_utils/. ¿Hay algo que pueda poner en app3/lib/my_utils.py para que Python> = 3.1 importe de forma transparente la carpeta python_lib/my_utils/ (usando rutas relativas y ..), y los subpaquetes también funcionarán?

Respuesta

3

Debe agregar esta ruta al sys.path. Por ejemplo:

lib_path = os.path.abspath(os.path.split(os.getcwd()+"/"+sys.argv[0])[0]+"/../_lib/my_utils/") 
sys.path.append(lib_path) 
+0

Esto no funcionaría si se pone en 'my_utils.py', ya que la ubicación de importación ya está resuelto para entonces. Si ejecuto esto antes de mi código principal, todavía no funcionará, porque cada subpaquete en 'my_utils' aparecería en el nivel superior de Python, y las importaciones relativas dentro de' my_utils' no funcionarían. – zildjohn01

+0

Normalmente establezco rutas desde mi script 'run'. De lo contrario, no tiene mucho sentido. También podría intentar jugar con la variable de entorno 'PYTHONPATH'. Más información aquí http://docs.python.org/tutorial/modules.html#the-module-search-path – Elalfer

5

que tendrá que ejecutar algo antes app3/run.py alcanza la declaración de importación.

import python_lib 
import sys 
sys.modules['lib'] = python_lib 
# ... 
from lib import etc 
print etc.__file__ 
print dir(etc) 
0

me hicieron los siguientes cambios en la estructura de directorios para simplificar el ejemplo:

  • crear root/python_lib/__ init__.py
  • de cambio de nombre/python_lib a raíz/lib
  • reemplazar root/app3/lib/con lib.py

Coloque el siguiente código en root/app3/lib.py

import os 
import sys 

pth = os.path.sep.join(sys.argv[0].split(os.path.sep)[0:-2]) 
sys.path.insert(0, pth) 
del sys.modules[__name__] 
import lib 

Básicamente, tenemos un módulo ficticio que reemplaza su propia referencia en sys.modules con una referencia a un módulo o paquete en otra ubicación.

0

¿Qué tal esto? (Sí, lo puso en app3/lib/my_utils.py.)

import os 
_f = os.path.realpath(__file__) 
_f = os.path.dirname(_f) 
_f = os.path.dirname(_f) 
_f = os.path.dirname(_f) 
_f = os.path.join(_f, 'python_lib') 
def f(): 
    path = sys.path 
    path.insert(0, _f) 
    sys.modules['lib.my_utils'] = __import__('my_utils') 
    path.pop(0) 
f() 
1

Añadir __init__.py a la carpeta python_lib app3/run.py contiene

import python_lib.my_utils 
import os 

sys.modules['lib.my_utils'] = python_lib.my_utils 
-1

muy tarde para esto, pero esto es muy fácil. Todo lo que necesita hacer es modificar el atributo __path__ de su paquete para que apunte a la carpeta donde están sus módulos. Esto requerirá que lib sea un paquete, no solo un módulo (es decir, una carpeta con un __init__.py). De forma predeterminada, __path__ es una lista de un elemento que contiene la ruta de la carpeta que es el paquete: ['/path/to/lib']. Es decir, que de manera predeterminada, Python busca submódulos en la carpeta del módulo (parece una cosa muy lógica).

Puede modificar el contenido de la ruta para que apunte a donde quiera, pero debe contener rutas absolutas. Si solo anexapath/to/lib_python, python buscará lib primero, buscar my_utils.py y luego detener. Por lo tanto, en ese caso deberá eliminar my_utils.py o poner la nueva ruta al frente de __path__ para que primero se busque la ubicación.Esto también significa que la carpeta lib puede contener sus propios módulos suplementarios para las bibliotecas compartidas y seguir funcionando.

En la práctica:

lib/__ init__.py

from os.path import join 
__path__.insert(0, join(__path__[0], "..", "..", "python_lib")) 
Cuestiones relacionadas