Experiencia de los "nuevos ganchos de importación PEP-302" de Python [cerrado]


41

Soy uno de los desarrolladores de Ruby (CRuby). Estamos trabajando en el lanzamiento de Ruby 2.0 (previsto para el lanzamiento 2012 / Feb).

Python tiene "PEP302: Nuevos ganchos de importación" (2003):

Este PEP propone agregar un nuevo conjunto de ganchos de importación que ofrecen una mejor personalización del mecanismo de importación de Python. Al contrario del gancho de importación actual , se puede inyectar un nuevo gancho de estilo en el esquema existente, lo que permite un control más detallado 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 desde sistemas de archivos de una manera estándar.

Si tiene alguna experiencia o consideración sobre PEP 302, por favor comparta.

Ejemplo:

  1. Es una gran especificación. No hay necesidad de cambiarlo.
  2. Es casi bueno, pero tiene este problema ...
  3. Si pudiera volver a 2003, cambiaría la especificación a ...

66
Wow, el chico de YARV, ¡hola y bienvenido a Programmers! ;) En Stack Exchange realmente no nos gusta la discusión abierta, nos encanta resolver problemas específicos en su lugar (lea rápidamente nuestras preguntas frecuentes ), lo que supongo es por qué su pregunta se cerró en Stack Overflow y ya tiene un Voto cerrado aquí. Debería intentar hacer esto un poco más específico: ¿tiene una preocupación específica sobre PEP 302 que motivó esta pregunta?
Yannis

44
Gracias por tu comentario, Yannis. Creo que quiero discutir sobre "arquitectura de software". PEP302 parece un marco poderoso y general para extender sus propios cargadores en el intérprete de Python. Sin embargo, una característica poderosa tiene riesgos como el uso excesivo (genera códigos mágicos), lo que impide la optimización del intérprete. Entonces, quiero saber que este marco de extensión es bueno o no para los usuarios de Python y los desarrolladores de intérpretes. Creo que estudiar historia me ayudará a hacer buenas especificaciones en Ruby 2.0.
Koichi Sasada

Gracias modificando mi pregunta bonita. Y lo siento si esta pregunta no es preferible.
Koichi Sasada

Este es un ejemplo fantástico de cómo una pregunta que parece, en la superficie, fallar en nuestra prueba de "encuesta de opinión", sin embargo, puede demostrar tener un valor sorprendente.
Ross Patterson el

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 preocupaciones de compatibilidad con versiones anteriores, hay muchas cosas que son más incómodas de lo que deberían ser.

Una cosa que duele con PEP 302 en Python es cuánto tiempo nos llevó convertir el sistema de importación principal para usarlo. Durante la mayor parte de una década, cualquiera que haya hecho algo complejo con los ganchos de importación se ha quedado atascado implementando dos piezas: una que maneja cargadores compatibles con PEP 302 (como las importaciones 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 cargadores PEP 302 también se encargará de manejar los módulos importados a través del mecanismo de importación del 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 con porciones a los paquetes de espacios de nombres. También soluciona un problema de nomenclatura en la definición de la API del Finder (reemplazando efectivamente el "find_module" con el nombre "find_loader" más preciso). Con suerte, esto debería documentarse más claramente en la especificación del idioma para cuando 3.3rc1 llegue en un par de semanas.

Otro problema notable es que el enfoque documentado específicamente en PEP 302 tiene demasiado estado global del proceso. No nos siga por ese camino: intente encapsular el estado en un modelo de objeto 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 pesadilla de hacer que dicha 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/) analiza una posible evolución hacia atrás compatible del enfoque de Python con una encapsulación de estado mejorada. Sin embargo, si tiene un modelo de estado encapsulado desde el principio, puede definir sus API en consecuencia y evitar que los importadores y los cargadores accedan al estado global (en su lugar, se le pasa una referencia al motor activo).

Otra pieza que falta en PEP 302 es la capacidad de pedirle a un importador un iterador sobre los módulos proporcionados por ese importador (esto es necesario para cosas como congelar utilidades y utilidades de documentación automática que extraen cadenas de documentos). Dado que es increíblemente útil, probablemente sea mejor estandarizarlo desde el principio: http://docs.python.org/dev/library/pkgutil#pkgutil.iter_modules (probablemente finalmente elevaremos esto a una especificada formalmente API en Python 3.4)

Y mi último comentario es que debe observar de cerca la división de responsabilidad 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 e importlib son un excelente punto de partida para un sistema de importación más flexible, pero definitivamente hay errores que vale la pena evitar.


1
Todavía no están del todo terminados, pero se puede encontrar un borrador inicial de los documentos completos del sistema de importación en docs.python.org/dev/reference/import
ncoghlan

1
python.org/dev/peps/pep-0451 es una actualización del sistema de importación de Python para Python 3.4 que aborda muchos de los comentarios de Brett y yo aquí.
ncoghlan

28

Junto a ncoghlan, soy el otro responsable 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). Estoy de acuerdo con todo lo que Nick dijo, así que solo quiero agregar información adicional.

Primero, no confíe demasiado en PEP 302 directamente, sino que observe lo que importlib proporciona en términos de clases base abstractas, etc. Para que las cosas fueran compatibles con versiones anteriores, tenía que ser compatible con PEP 302, pero tuve que agregar algunas de mis APIs propias para terminar de desarrollar el soporte para una verdadera flexibilidad.

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

Si bien este último rara vez se necesita, el primero es donde debe preocuparse por el soporte. Y aquí es donde terminas redefiniendo prácticamente 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 leer archivos, descubrir archivos, etc. Todavía tenemos que implementar la parte de la API para descubrir qué archivos de datos están disponibles, enumerarlos, etc. .

Pero también tiene la necesidad de API que sean específicas del código. Como Nick mencionó, terminas necesitando API 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 manejar módulos en los que ha extraído el concepto de archivos, pero luego termina necesitando proporcionar API para acceder a datos de activos similares a archivos. Y tan pronto como intente implementar uno en relación con el otro para evitar la duplicación, las aguas se vuelven realmente turbias (es decir, las personas terminan confiando en la estructuración esperada de la ruta del archivo, 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 estarás mejor a largo plazo.

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


-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 las importaciones en Python, existe una larga historia de complejidad que pronto se simplificará con la introducción de una implementación de importación en Python.

Debo aconsejar pensar mucho sobre los casos de esquina. Entonces es probable que obtenga una implementación útil.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.