Experiencia de “PEP-302 New Import Hooks” de Python [cerrado]

40

Soy uno de los desarrolladores de Ruby (CRuby). Estamos trabajando en la versión Ruby 2.0 (prevista para 2012 / febrero).

Python tiene "PEP302: New Import Hooks" (2003):

  

Este PEP propone agregar un nuevo conjunto de ganchos de importación que ofrezcan una mejor personalización del mecanismo de importación de Python. Contrariamente al gancho actual , se puede inyectar un nuevo estilo en el esquema existente, lo que permite un control más preciso de cómo se encuentran los módulos y cómo se cargan.

Estamos considerando introducir una característica similar a PEP302 en Ruby 2.0 (CRuby 2.0). Quiero hacer una propuesta que pueda persuadir a Matz. Actualmente, CRuby puede cargar scripts solo de sistemas de archivos de forma estándar.

Si tiene alguna experiencia o consideración sobre PEP 302, compártala.

Ejemplo:

  1. Es una gran especificación. No es necesario cambiarlo.
  2. Es casi bueno, pero tiene este problema ...
  3. Si pudiera volver a 2003, cambiaría la especificación a ...
pregunta Koichi Sasada 26.06.2012 - 07:35

3 respuestas

47

Soy el mantenedor del módulo runpy de Python y uno de los mantenedores del sistema de importación actual. Si bien nuestro sistema de importación es impresionantemente flexible, aconsejaría no adoptarlo al por mayor sin hacer algunos ajustes, debido a problemas de compatibilidad con versiones anteriores, hay muchas cosas que son más difíciles de lo que deberían ser.

Una cosa que duele con PEP 302 en Python es el tiempo que tardamos en convertir el sistema de importación principal en usarlo. Durante la mayor parte de una década, cualquiera que esté haciendo algo complejo con los ganchos de importación se ha quedado atascado implementando dos partes: una que maneja cargadores compatibles con PEP 302 (como las importaciones de archivos zip), y una segunda que maneja el mecanismo de importación basado en el sistema de archivos estándar. Es solo en el próximo 3.3 que el manejo de los cargadores PEP 302 también se encargará de manejar los módulos importados a través del mecanismo de importación de sistema de archivos estándar. Intenta no repetir ese error si puedes evitarlo.

PEP 420 (implementado para Python 3.3) hace algunas adiciones al protocolo para permitir que los importadores contribuyan porciones a los paquetes de espacio de nombres. También soluciona un problema de denominación en la definición de la API del Finder (reemplazando de manera efectiva el mal llamado "find_module" por el más preciso "find_loader"). Es de esperar que todo esto se documente más claramente en la especificación de idioma para el momento en que 3.3rc1 entre en un par de semanas.

Otro problema notable es que el enfoque documentado específicamente en PEP 302 tiene demasiado estado global de proceso. No nos siga por ese camino: intente encapsular el estado en un modelo de objetos más coherente para que sea un poco más fácil importar selectivamente otros módulos (los módulos de extensión C son la ruina de hacer que cualquier encapsulación sea completamente efectiva, pero incluso un cierto nivel de encapsulación puede ser útil).

PEP 406 (http://www.python.org/dev/peps/pep-0406/) discute una posible evolución compatible hacia atrás del enfoque de Python con una mejor encapsulación de estados. Sin embargo, si tiene un modelo de estado encapsulado desde el principio, puede definir sus API en consecuencia y evitar que los importadores y cargadores accedan al estado global (en lugar de pasar una referencia al motor activo).

Otra pieza faltante en PEP 302 es la capacidad de solicitar a un importador un iterador sobre los módulos provistos por ese importador (esto es necesario para cosas como las utilidades de congelación y las utilidades de documentación automática que extraen cadenas de documentos). Ya que es increíblemente útil, probablemente sería mejor estandarizarlo desde el principio: enlace (Probablemente finalmente lo elevemos a una API especificada formalmente en Python 3.4)

Y mi último comentario es que debe observar de cerca la división de responsabilidades entre el sistema de importación y los objetos del cargador. En particular, considere dividir la API "load_module" en pasos separados "init_module" y "exec_module". Eso debería permitirle minimizar el grado en que los cargadores necesitan interactuar directamente con el estado de importación.

PEP 302 y importlib son un excelente punto de partida para un sistema de importación más flexible, pero definitivamente cometemos errores que vale la pena evitar.

    
respondido por el ncoghlan 23.07.2012 - 08:12
28

Junto a ncoghlan, soy el otro mantenedor del sistema de importación de Python y el autor de su implementación actual, importlib (http://docs.python.org/dev/py3k/library/importlib.html). Todo lo que Nick dijo que estoy de acuerdo, así que solo quiero agregar información adicional.

Primero, no confíe demasiado en PEP 302 directamente, sino que mire lo que proporciona importlib en términos de clases base abstractas, etc. Para que la compatibilidad con versiones anteriores fuera compatible con PEP 302, tuve que agregar algunas de mis propias API para terminar de desarrollar el soporte para una verdadera flexibilidad.

Otro punto importante es que le está dando a los desarrolladores dos elementos de flexibilidad. Una de ellas es la capacidad de almacenar código de una manera que no sea directamente en el sistema de archivos como archivos individuales (yo lo llamo back-end de almacenamiento para importaciones), por ejemplo. esto es permitir que el código viva en un archivo zip, una base de datos sqlite, etc. El otro soporte es permitir que el control realice el procesamiento previo o posterior del código de alguna manera, por ejemplo. Quixote (https://www.mems-exchange.org/software/quixote/) y su uso alternativo de cadenas literales no asignadas a una variable serían mucho más fáciles de soportar.

Mientras que lo último rara vez es necesario, lo primero es donde tienes que preocuparte por el soporte. Y aquí es donde terminas prácticamente redefiniendo las API de interacción del sistema de archivos. Dado que algunas personas necesitan activos almacenados como archivos con su código, debe proporcionar una buena manera de leerlos, descubrirlos, etc. Todavía necesitamos implementar la parte de la API para descubrir qué archivos de datos están disponibles, enumerarlos, etc. .

Pero también necesitas las API que son específicas del código. Como Nick mencionó, terminas necesitando APIs para descubrir qué módulos contiene un paquete, etc. que no son específicos de un archivo. Existe esta extraña dualidad de tener API para tratar con módulos en los que ha extraído el concepto de archivos, pero luego tiene que proporcionar API para acceder a datos de activos similares a archivos. Y tan pronto como intenta implementar una en relación con la otra para evitar la duplicación, las aguas se vuelven realmente turbias (es decir, las personas terminan confiando en la estructuración de la ruta del archivo esperado, etc. sin prestar atención al hecho de que la ruta puede no ser una ruta verdadera). porque es para un archivo zip que contiene código y no solo un archivo). IOW, terminarás teniendo que implementar dos API similares, pero a la larga estarás en mejores condiciones.

Como dijo Nick, nuestra solución es un buen punto de partida, pero no es como lo haría hoy si estuviera diseñando la API desde cero.

    
respondido por el Brett Cannon 23.07.2012 - 16:27
-1

PEP 302 le permite conectarse al mecanismo de importación de Python, lo que significa que puede importar código de otras fuentes como bases de datos, archivos zip, etc.

En la implementación de importaciones de Python, existe un largo historial de complejidad que pronto se simplificará con la introducción de una implementación de importación de Python.

Debería aconsejarte pensar mucho sobre los casos de esquina. Entonces es probable que obtengas una implementación útil.

    
respondido por el holdenweb 23.07.2012 - 06:59

Lea otras preguntas en las etiquetas