tipos - ¿Cómo(en qué forma) compartir(entregar) una función de Python?
variables globales python 3 (5)
El resultado final de mi trabajo debería ser una función de Python que tome un objeto JSON como la única entrada y devuelva otro objeto JSON como salida. Para ser más específico, soy un científico de datos, y la función de la que estoy hablando se deriva de los datos y ofrece predicciones (en otras palabras, es un modelo de aprendizaje automático).
Entonces, mi pregunta es cómo entregar esta función al "equipo técnico" que la incorporará en un servicio web.
Por el momento me enfrento a pocos problemas. Primero, el equipo técnico no necesariamente trabaja en el entorno Python. Por lo tanto, no pueden simplemente "copiar y pegar" mi función en su código. En segundo lugar, quiero asegurarme de que mi función se ejecute en el mismo entorno que el mío. Por ejemplo, puedo imaginar que utilizo alguna biblioteca que el equipo técnico no tiene o tienen una versión que difiere de la versión que uso.
ADICIONAL
Como posible solución considero lo siguiente. Comienzo un proceso de Python que escucha un socket, acepto cadenas entrantes, las transforma en JSON, le da a JSON la función "publicada" y devuelve el JSON de salida como una cadena. ¿Esta solución tiene desventajas? En otras palabras, ¿es una buena idea "publicar" una función de Python como un proceso en segundo plano escuchando un socket?
Como ya se sugirió en otras respuestas, la mejor opción sería crear un servicio web simple. Además de Flask, es posible que desee probar la botella, que es un marco web muy delgado de un solo archivo. Su servicio puede parecer tan simple como:
from bottle import route, run, request
@route(''/'')
def index():
return my_function(request.json)
run(host=''0.0.0.0'', port=8080)
Con el fin de mantener los entornos, la misma verificación virtualenv para hacer un entorno aislado para evitar conflictos con los paquetes ya instalados y pip para instalar la versión exacta de los paquetes en el entorno virtual.
Mi comprensión de su pregunta se reduce a:
¿Cómo puedo compartir una biblioteca de Python con el resto de mi equipo, que de lo contrario no podría usar Python?
¿Y cómo puedo asegurarme de que mi código y sus dependencias sean lo que ejecutará el equipo receptor?
¿Y que el equipo receptor puede instalar las cosas fácilmente en cualquier lugar?
Esta es una pregunta simple sin una respuesta directa ... ya que acaba de mencionar que puede estar integrado en algún servicio web, pero no conoce la plataforma real para este servicio.
También preguntas:
Como posible solución considero lo siguiente. Comienzo un proceso de Python que escucha un socket, acepto cadenas entrantes, las transforma en JSON, le da a JSON la función "publicada" y devuelve el JSON de salida como una cadena. ¿Esta solución tiene desventajas? En otras palabras, ¿es una buena idea "publicar" una función de Python como un proceso en segundo plano escuchando un socket?
En el caso más sencillo y para empezar diría que no en general. Iniciar servidores de red como un servidor HTTP (que está integrado en Python) es muy fácil. Pero un servicio (incluso si está calificado como "micro") significa infraestructura, significa seguridad, etc.
- ¿Qué sucede si el puerto que espera no está disponible en la máquina de implementación? - ¿Qué pasa cuando reinicias esa máquina?
- ¿Cómo se iniciará o reiniciará su servidor cuando haya una falla?
- ¿Necesitaría también proporcionar un servicio upstart o systemd (en Linux)?
- ¿Su simple socket o servidor web soportará múltiples solicitudes concurrentes?
- ¿Existe un riesgo de seguridad al exponer un socket?
Etc, etc. Cuando se implementa, mi experiencia con los servidores de socket "simples" es que, al fin y al cabo, no son tan simples.
En la mayoría de los casos, será más sencillo evitar la redistribución de un servicio de socket al principio. Y el enfoque propuesto aquí podría utilizarse para empaquetar un servicio completo en una etapa posterior de una manera más simple si lo desea.
Lo que sugiero en su lugar es una sencilla interfaz de línea de comandos bien empaquetada para su instalación .
El conjunto mínimo de cosas a considerar sería:
- proporciona un mecanismo portátil para llamar a su función en muchos sistemas operativos
- asegúrese de empaquetar su función de modo que pueda instalarse con todas las dependencias correctas
- Facilita la instalación y, por supuesto, proporciona algunos documentos.
Paso 1. El denominador común más simple sería proporcionar una interfaz de línea de comandos que acepte la ruta a un archivo JSON y escupe JSON en la salida estándar. Esto se ejecutaría en Linux, Mac y Windows.
Las instrucciones aquí deberían funcionar en Linux o Mac y necesitarían un pequeño ajuste para Windows (solo para el script configure.sh
más abajo)
Una secuencia de comandos de Python mínima podría ser:
#!/usr/bin/env python
"""
Simple wrapper for calling a function accepting JSON and returning JSON.
Save to predictor.py and use this way::
python predictor.py sample.json
[
"a",
"b",
4
]
"""
from __future__ import absolute_import, print_function
import json
import sys
def predict(json_input):
"""
Return predictions as a JSON string based on the provided `json_input` JSON
string data.
"""
# this will error out immediately if the JSON is not valid
validated = json.loads(json_input)
# <....> your code there
with_predictions = validated
# return a pretty-printed JSON string
return json.dumps(with_predictions, indent=2)
def main():
"""
Print the JSON string results of a prediction, loading an input JSON file from a
file path provided as a command line argument.
"""
args = sys.argv[1:]
json_input = args[0]
with open(json_input) as inp:
print(predict(inp.read()))
if __name__ == ''__main__'':
main()
Puede procesar entradas eventualmente grandes pasando la ruta a un archivo JSON.
Paso 2. Empaque su función. En Python esto se logra creando un script setup.py
. Esto se encarga de instalar cualquier código dependiente de Pypi también. Esto asegurará que la versión de las bibliotecas de las que dependa sea la que espera. Aquí agregué nltk
como ejemplo para una dependencia. Agregue el suyo: esto podría ser scikit-learn
, pandas
, numpy
, etc. Este setup.py
también crea automáticamente un script bin/predict
que será su interfaz de línea de comando principal:
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
from __future__ import absolute_import, print_function
from setuptools import setup
from setuptools import find_packages
setup(
name=''predictor'',
version=''1.0.0'',
license=''public domain'',
description=''Predict your life with JSON.'',
packages=find_packages(),
# add all your direct requirements here
install_requires=[''nltk >= 3.2, < 4.0''],
# add all your command line entry points here
entry_points={''console_scripts'': [''predict = prediction.predictor:main'']}
)
Además, como es común en Python y para simplificar el código de configuración, creé un directorio del "paquete Python" moviendo el predictor dentro de este directorio.
Paso 3. Ahora quieres empaquetar cosas que sean fáciles de instalar. Un simple script configure.sh
hace el trabajo. Instala virtualenv
, pip
y setuptools
, luego crea un virtualenv
en el mismo directorio que su proyecto y luego instala su herramienta de predicción allí ( pip install .
Es esencialmente lo mismo que python setup.py install
). Con este script, se asegura de que el código que se ejecutará es el código que desea ejecutar con las dependencias correctas. Además, se asegura de que se trata de una instalación aislada con mínimas dependencias e impacto en el sistema de destino. Esto se prueba con Python 2, pero también debería funcionar en Python 3.
#!/bin/bash
#
# configure and installs predictor
#
ARCHIVE=15.0.3.tar.gz
mkdir -p tmp/
wget -O tmp/venv.tgz https://github.com/pypa/virtualenv/archive/$ARCHIVE
tar --strip-components=1 -xf tmp/venv.tgz -C tmp
/usr/bin/python tmp/virtualenv.py .
. bin/activate
pip install .
echo ""
echo "Predictor is now configured: run it with:"
echo " bin/predict <path to JSON file>"
Al final, tiene una pieza de código totalmente configurada, aislada y fácil de instalar con una interfaz de línea de comandos simple y altamente portátil. Puedes verlo todo en este pequeño repositorio: https://github.com/pombredanne/predictor Simplemente clonas o obtienes un zip o tarball del repositorio, luego pasas por el README y estás en el negocio.
Tenga en cuenta que para una forma más activa de aplicaciones más complejas, como la venta de dependencias para una instalación fácil y no la red, puede consultar este https://github.com/nexB/scancode-toolkit que también mantengo.
Y si realmente desea exponer un servicio web, puede reutilizar este enfoque y paquete con un servidor web simple (como el que está incorporado en la biblioteca estándar de Python o una botella o frasco o gunicornio) y proporcionar configure.sh
para instalar Todo y generar la línea de comandos para lanzarlo.
Su tarea es (en general) sobre la producción de un modelo de aprendizaje automático, donde el consumidor del modelo puede no estar trabajando en el mismo entorno que el que se utilizó para desarrollar el modelo. He estado tratando de abordar este problema desde los últimos años. Muchas empresas se enfrentan al problema y se agrava debido al conjunto de habilidades, objetivos y desajuste del entorno (idiomas, tiempo de ejecución) entre los científicos de datos y los desarrolladores. Desde mi experiencia, las siguientes soluciones / opciones están disponibles, cada una con sus ventajas y desventajas únicas.
Opción 1 : cree la parte de predicción de su modelo como un servicio web independiente utilizando cualquier herramienta liviana en Python (por ejemplo, Flask). Debe tratar de desacoplar la parte de desarrollo / entrenamiento y predicción del modelo tanto como sea posible. El modelo que ha desarrollado debe ser serializado de alguna forma para que el servidor web pueda usarlo.
- ¿Con qué frecuencia se actualiza su modelo de aprendizaje automático? Si no se hace con mucha frecuencia, el archivo de modelo serializado (ejemplo: archivo de pickle de Python) se puede guardar en una ubicación común accesible al servidor web (por ejemplo, s3), cargado en la memoria. El servidor web independiente debe ofrecer API para la predicción.
Tenga en cuenta que exponer una predicción de un solo modelo utilizando Flask sería simple. Pero escalar este servidor web si es necesario, configurarlo con el conjunto correcto de bibliotecas, la autenticación de las solicitudes entrantes son tareas no triviales. Debe elegir esta ruta solo si tiene equipos de desarrollo listos para ayudar con estos.
Si el modelo se actualiza con frecuencia, la versión del archivo de su modelo sería una buena opción. De hecho, puede superarse a cualquier sistema de control de versiones comprobando el archivo de modelo completo si no es demasiado grande. El servidor web puede des-serializar (pickle.load) este archivo en el inicio / actualización y convertirlo en un objeto Python en el que puede llamar a los métodos de predicción.
Opción 2 : usar lenguaje de marcado de modelado predictivo . PMML fue desarrollado específicamente para este propósito: modelado predictivo de intercambio de datos en formato independiente del entorno. Entonces, el científico de datos puede desarrollar un modelo, exportarlo a un archivo PMML. El servidor web utilizado para la predicción puede consumir el archivo PMML para hacer predicciones. Definitivamente, debe verificar el proyecto de puntuación abierta que le permite exponer modelos de aprendizaje automático a través de las API REST para implementar modelos y hacer predicciones.
- Pros: PMML es un formato estandarizado, Open Scoring es un proyecto maduro con un buen historial de desarrollo.
- Contras: PMML puede no ser compatible con todos los modelos. La puntuación abierta es principalmente útil si la plataforma de desarrollo de su equipo técnico es JVM. Exportar modelos de aprendizaje automático de Python no es sencillo. Pero R tiene un buen soporte para exportar modelos como archivos PMML.
- Opción 3 : hay algunos proveedores que ofrecen soluciones dedicadas para este problema . Tendrá que evaluar el costo de la licencia, el costo del hardware y la estabilidad de las ofertas para tomar esta ruta.
Cualquiera que sea la opción que elija, tenga en cuenta los costos a largo plazo de respaldar esa opción. Si su trabajo se encuentra en una etapa de prueba de concepto, el servidor web basado en matraz de Python + los archivos de modelo en escabeche serán la mejor ruta. Espero que esta respuesta te ayude!
Supongo que tienes 3 posibilidades:
- convertir la función python a la función javascript:
Suponiendo que el "equipo técnico" use Javascript para el servicio web, puede intentar convertir su función python directamente a una función Javascript (que será realmente fácil de integrar en la página web) usando empythoned (basado en emscripten )
El punto negativo de este método es que cada vez que necesite actualizar / actualizar su función python, también necesita convertir a Javascript nuevamente, luego verificar y validar que la función continúe funcionando.
- API simple servidor + JQuery
Si el método de conversión es imposible, estoy de acuerdo con @ justin-bell, puede usar FLASK
obteniendo JSON como entrada> JSON a su parámetro de función> ejecute python function> convierte el resultado de la función a JSON> sirva el resultado de JSON
Suponiendo que elija la solución FLASK, el "equipo técnico" solo tendrá que enviar un mensaje asíncrono. La solicitud GET / POST que contiene todos los argumentos como JSON obj, cuando necesitan obtener algún resultado de su función python.
- servidor websocket + socket.io
También puede usar Echar un vistazo en Websocket para enviarlo al servicio web (consulte flask + websocket para su lado y socket.io para el servicio web).
=> websocket es realmente útil cuando necesita enviar / recibir datos con bajo costo y latencia a (o de) muchos usuarios (no estoy seguro de que websocket sea el mejor para su necesidad)
Saludos
Tienes la idea correcta con el uso de un socket, pero hay muchos marcos que hacen exactamente lo que quieres. Como hleggs , te sugiero que compruebes a Flask para construir un microservicio. Esto permitirá que el otro equipo publique objetos JSON en una solicitud HTTP a su aplicación de matraz y reciba los objetos JSON nuevamente. Ningún conocimiento del sistema subyacente o requisitos adicionales requeridos!
Aquí hay una plantilla para una aplicación de matraz que responde y responde con JSON
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route(''/'', methods=[''POST''])
def index():
json = request.json
return jsonify(your_function(json))
if __name__==''__main__'':
app.run(host=''0.0.0.0'', port=5000)
Edición : incrusté mi código directamente según el consejo de Peter Britain