Marco de dependency injection de Python

¿Existe un marco equivalente a Guice ( http://code.google.com/p/google-guice ) para Python?

No lo he usado, pero el framework Spring Python está basado en Spring e implementa Inversion of Control .

También parece haber un proyecto Guice in Python: snake-guice

Spring Python es una división del Spring Framework y Spring Security basado en Java, diseñado para Python. Este proyecto actualmente contiene las siguientes características:

  • Inversión de control (dependency injection) : use el XML clásico o el decorador pyOton @Object (similar al subproyecto Spring JavaConfig) para conectar cosas. Si bien el formato @Object no es idéntico al estilo Guice (cableado centralizado vs. información de cableado en cada clase), es una forma valiosa de conectar su aplicación python.
  • Progtwigción orientada a aspectos : aplique los interceptores en un paradigma de progtwigción horizontal (en lugar de la herencia OOP vertical) para cosas como transacciones, seguridad y almacenamiento en caché.
  • DatabaseTemplate: la lectura de la base de datos requiere un ciclo monótono de cursores de apertura, filas de lectura y cursores de cierre, junto con controladores de excepciones. Con esta clase de plantilla, todo lo que necesita es la consulta SQL y la función de manejo de filas. Spring Python hace el rest.
  • Transacciones de base de datos: envolver múltiples llamadas de base de datos con transacciones puede hacer que su código sea difícil de leer. Este módulo proporciona múltiples formas de definir transacciones sin complicar las cosas.
  • Seguridad: conecte los interceptores de seguridad para bloquear el acceso a sus métodos, utilizando la autenticación y la autorización de dominio.
  • Comunicación remota: es fácil convertir su aplicación local en una distribuida. Si ya ha creado las piezas de su cliente y servidor utilizando el contenedor IoC, pasar de local a distribuido es solo un cambio de configuración.
  • Muestras: para ayudar a demostrar varias características de Spring Python, se han creado algunas aplicaciones de muestra:
    • PetClinic: la aplicación web de muestra de Spring Framework se ha reconstruido desde cero utilizando contenedores web de python, entre los que se incluyen: CherryPy . Vaya a ver un ejemplo de cómo usar este marco. (NOTA: en el futuro se agregarán otros marcos web de Python a esta lista).
    • Spring Wiki: los wikis son formas poderosas de almacenar y administrar contenido, ¡así que creamos uno simple como demostración!
    • Spring Bot: use Spring Python para crear un pequeño bot para administrar el canal IRC de su proyecto de código abierto.

Me gusta este marco simple y ordenado.

http://pypi.python.org/pypi/injector/

La dependency injection como patrón formal es menos útil en Python que en otros idiomas, principalmente debido a su compatibilidad con los argumentos de palabras clave, la facilidad con la que se pueden burlar los objetos y su naturaleza dinámica.

Dicho esto, un marco para ayudar en este proceso puede eliminar una gran cantidad de placas de calderas de aplicaciones más grandes. Ahí es donde Injector puede ayudar. Proporciona de forma automática y transitiva argumentos de palabras clave con sus valores. Como beneficio adicional, Injector fomenta un código bien compartimentado mediante el uso de Módulos.

Aunque está inspirado en Guice, no replica servilmente su API. Proporcionar una API de Pythonic triunfa sobre la fidelidad.

Como alternativa a la crianza de monos, me gusta DI. Un proyecto incipiente como http://code.google.com/p/snake-guice/ puede ajustarse a la factura.

O vea la publicación del blog Dependency Injection en Python por Dennis Kempin (agosto de 2008).

pinject ( https://github.com/google/pinject ) es una alternativa más nueva. Parece que lo mantiene Google y sigue un patrón similar al de Guice ( https://code.google.com/p/google-guice/ ), su contraparte de Java.

Aparte de eso:

  1. Componente Zope Architekture
  2. pyContainer

Hay un proyecto un poco Guicey de inyección de python . Es bastante activo, y mucho menos código que Spring-python, pero, de nuevo, todavía no he encontrado una razón para usarlo.

Si solo desea realizar una dependency injection en Python, no necesita un marco. Echa un vistazo a Dependency Injection the Python Way . Es realmente rápido y fácil, y solo c. 50 líneas de código.

Dejaré mis 5 centavos aquí 🙂

https://pypi.python.org/pypi/dependency_injector

"""Pythonic way for Dependency Injection.""" from dependency_injector import providers from dependency_injector import injections @providers.DelegatedCallable def get_user_info(user_id): """Return user info.""" raise NotImplementedError() @providers.Factory @injections.inject(get_user_info=get_user_info) class AuthComponent(object): """Some authentication component.""" def __init__(self, get_user_info): """Initializer.""" self.get_user_info = get_user_info def authenticate_user(self, token): """Authenticate user by token.""" user_info = self.get_user_info(user_id=token + '1') return user_info print AuthComponent print get_user_info @providers.override(get_user_info) @providers.DelegatedCallable def get_user_info(user_id): """Return user info.""" return {'user_id': user_id} print AuthComponent().authenticate_user(token='abc') # {'user_id': 'abc1'} 

ACTUALIZADO

Pasó un tiempo y el inyector de dependencia es un poco diferente ahora. Es mejor comenzar desde la página de GitHub del inyector de dependencia para obtener ejemplos reales: https://github.com/ets-labs/python-dependency-injector

Aquí hay un pequeño ejemplo de un contenedor de dependency injection que realiza una inyección del constructor en función de los nombres de argumento del constructor:

http://code.activestate.com/recipes/576609-non-invasive-dependency-injection/

Hice una biblioteca para hacer esto https://github.com/ettoreleandrotognoli/python-cdi Espero que eso ayude

Está disponible en pypi: https://pypi.python.org/pypi/pycdi

Con ella podrás realizar inyecciones con python2.

 import logging from logging import Logger from pycdi import Inject, Singleton, Producer from pycdi.shortcuts import call @Producer(str, _context='app_name') def get_app_name(): return 'PyCDI' @Singleton(produce_type=Logger) @Inject(app_name=str, _context='app_name') def get_logger(app_name): return logging.getLogger(app_name) @Inject(name=(str, 'app_name'), logger=Logger) def main(name, logger): logger.info('I\'m starting...') print('Hello World!!!\nI\'ma example of %s' % name) logger.debug('I\'m finishing...') call(main) 

Y usando sugerencias tipográficas de python3

 import logging from logging import Logger from pycdi import Inject, Singleton, Producer from pycdi.shortcuts import call @Producer(_context='app_name') def get_app_name() -> str: return 'PyCDI' @Singleton() @Inject(logger_name='app_name') def get_logger(logger_name: str) -> Logger: return logging.getLogger(logger_name) @Inject(name='app_name') def main(name: str, logger: Logger): logger.info('I\'m starting...') print('Hello World!!!\nI\'ma example of %s' % name) logger.debug('I\'m finishing...') call(main) 

Más simple que un marco es el decorador @autowired .

Este decorador proporciona una dependency injection limpia y un soporte de inicialización lento.

Gira código como este:

 def __init__(self, *, model: Model = None, service: Service = None): if model is None: model = Model() if service is None: service = Service() self.model = model self.service = service # actual code 

dentro de esto:

 @autowired def __init__(self, *, model: Model, service: Service): self.model = model self.service = service # actual code 

No es un marco, por lo que no hay ninguna configuración ni flujos de trabajo forzados, aunque no proporciona la manipulación de contextos de inyección.

Divulgación: Soy el encargado del proyecto.

Si prefiere una solución realmente pequeña, hay una pequeña función, es solo un configurador de dependencias.

https://github.com/liuggio/Ultra-Lightweight-Dependency-Injector-Python

Hay dyject ( http://dyject.com ), un marco ligero tanto para Python 2 como para Python 3 que utiliza el ConfigParser incorporado

Si quieres una idea similar (las nuevas nuevas como dicen), recientemente hice algo parecido en Python 3 que mejor se adaptaba a mis necesidades simples para un proyecto paralelo.

Todo lo que necesita es un @inject en un método (__init__ incluido, por supuesto). El rest se hace a través de anotaciones.

 from py3njection import inject from some_package import ClassToInject class Demo: @inject def __init__(self, object_to_use: ClassToInject): self.dependency = object_to_use demo = Demo() 

https://pypi.python.org/pypi/py3njection

Recientemente lancé una micro biblioteca limpia (IMHO) para DI en python:

https://github.com/suned/serum

Enterprython es un pequeño marco que proporciona una dependency injection, que crea el gráfico de objetos automáticamente en función de las sugerencias de tipo .