en primer lugar vamos a empezar con la forma from import
trabajo en Python:
Bueno en primer lugar vamos a ver el código de bytes:
>>> def foo():
... from foo import bar
>>> dis.dis(foo)
2 0 LOAD_CONST 1 (-1)
3 LOAD_CONST 2 (('bar',))
6 IMPORT_NAME 0 (foo)
9 IMPORT_FROM 1 (bar)
12 STORE_FAST 0 (bar)
15 POP_TOP
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
hmm interesting :), entonces from foo import bar
se traduce al primer IMPORT_NAME foo
que equivale a import foo
y luego IMPORT_FROM bar
.
¿Ahora qué IMPORT_FROM
hacer?
vamos a ver qué pitón hacer cuando se encontró IMPORT_FROM
:
TARGET(IMPORT_FROM)
w = GETITEM(names, oparg);
v = TOP();
READ_TIMESTAMP(intr0);
x = import_from(v, w);
READ_TIMESTAMP(intr1);
PUSH(x);
if (x != NULL) DISPATCH();
break;
Bueno, básicamente, él consiguió los nombres que desea importar, que está en nuestra función foo()
será bar
, entonces pop de la pila del marco el valor v
que es el retorno del código de operación ejecutada la última, que es IMPORT_NAME
, a continuación, llamar a la función import_from()
con estos dos argumentos:
static PyObject *
import_from(PyObject *v, PyObject *name)
{
PyObject *x;
x = PyObject_GetAttr(v, name);
if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Format(PyExc_ImportError, "cannot import name %S", name);
}
return x;
}
Como puede ver la función import_from()
es muy fácil, intente primero obtener el atributo name
del módulo v
, si no existe, suba ImportError
, más devuelva este atributo.
Ahora, ¿qué tiene que ver con la importación relativa?
La importación relativa bien como from . import b
son equivalentes, por ejemplo, en el caso que está en la pregunta OP a from pkg import b
.
¿Pero cómo sucede esto? Para entender esto, deberíamos echar un vistazo al módulo import.c
de python, especialmente a la función get_parent(). Como puede ver, la función es larga y silenciosa para enumerarla aquí, pero en general lo que hace cuando ve una importación relativa es intentar reemplazar el punto .
con el paquete principal dependiendo del módulo __main__
, que es nuevamente de la pregunta OP es el paquete pkg
.
Ahora vamos a poner todo junto y tratar de averiguar por qué terminamos con el comportamiento en la pregunta OP.
Para esto nos ayudará si podemos ver lo que python hacer al hacer importaciones, bueno, es nuestro día de suerte python venir ya con esta característica que se puede habilitar ejecutando en modo extra verbose -vv
.
Así, utilizando la línea de comandos: python -vv -c 'import pkg.b'
:
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
import pkg # directory pkg
# trying pkg/__init__.so
# trying pkg/__init__module.so
# trying pkg/__init__.py
# pkg/__init__.pyc matches pkg/__init__.py
import pkg # precompiled from pkg/__init__.pyc
# trying pkg/b.so
# trying pkg/bmodule.so
# trying pkg/b.py
# pkg/b.pyc matches pkg/b.py
import pkg.b # precompiled from pkg/b.pyc
# trying pkg/a.so
# trying pkg/amodule.so
# trying pkg/a.py
# pkg/a.pyc matches pkg/a.py
import pkg.a # precompiled from pkg/a.pyc
# clear[2] __name__
# clear[2] __file__
# clear[2] __package__
# clear[2] __name__
# clear[2] __file__
# clear[2] __package__
...
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "pkg/b.py", line 1, in <module>
from . import a
File "pkg/a.py", line 2, in <module>
from . import a
ImportError: cannot import name a
# clear __builtin__._
hmm lo que acaba de ocurrir antes de que el ImportError
?
primero)from . import a
en pkg/b.py
se llama, que se traduce como se explicó anteriormente para from pkg import a
, que está de nuevo en bytecode es equivalente a import pkg; getattr(pkg, 'a')
. Pero espere un minuto a
¿es también un módulo? Bueno, aquí viene la parte divertida si tenemos algo como from module|package import module
, en este caso se producirá una segunda importación que es la importación del módulo en la cláusula de importación. Entonces, de nuevo en el ejemplo de OP ahora necesitamos importar pkg/a.py
, y como saben, antes de nada, configuramos en nuestra sys.modules
una clave para nuestro nuevo módulo que será pkg.a
y luego continuamos nuestra interpretación del módulo pkg/a.py
, pero antes del módulo pkg/a.py
finalícela importando llame al from . import b
.
Ahora llegado el Segunda) parte, pkg/b.py
se importará y en ella a su vez será primer intento de import pkg
que por pkg
está ya importó lo que no hay una clave pkg
en nuestra sys.modules
sólo devolverá el valor de esa llave. Luego se import b
establecer la clave pkg.b
en sys.modules
y comenzar la interpretación. ¡Y llegamos a esta línea from . import a
!
Peropkg/a.py
recordar que ya se importa lo que significa ('pkg.a' in sys.modules) == True
por lo que la importación se saltará, y sólo el getattr(pkg, 'a')
serán llamados, pero ¿qué pasará? Python no terminó de importar pkg/a.py
!? Por lo tanto, solo se llamará a getattr(pkg, 'a')
, y esto aumentará un AttributeError
en la función import_from()
, que se traducirá al ImportError(cannot import name a)
.
DISCLAIM: Este es mi propio esfuerzo para entender lo que está sucediendo dentro del intérprete, estoy muy lejos de ser un experto.
EDIT: esta pregunta reformulada porque cuando he intentado volver a leerlo me comentó que mi respuesta fue mal formulada, esperan ahora será más útil :)
Puede especificar los detalles del 'ImportError' que está recibiendo al cambiar a' from. importar b'? –
¿Cómo ejercitas este código? ¿Tiene otro módulo en 'pkg' que hace algo como:' if __name__ == 'main': from. importar a'? Si es así, le recomendamos que lea [PEP 366] (http://python.org/dev/peps/pep-0366/), este PEP facilita el uso de importaciones relativas desde módulos ejecutables con paquetes. –
si __a__ depende de __b__ y __b__ depende de __a__ ¿por qué no unir ambos en el mismo archivo? – JBernardo