Подтвердить что ты не робот

Как (в какой форме) передать (доставить) функцию Python?

Конечным результатом моей работы должна быть функция Python, которая принимает объект JSON как единственный вход и возвращает другой объект JSON в качестве вывода. Чтобы быть более конкретным, я являюсь ученым-информатором, и функция, о которой я говорю, получена из данных и обеспечивает прогнозы (другими словами, это модель машинного обучения).

Итак, мой вопрос заключается в том, как доставить эту функцию в "техническую команду", которая собирается включить ее в веб-службу.

В настоящий момент у меня мало проблем. Во-первых, техническая команда не обязательно работает в среде Python. Таким образом, они не могут просто "скопировать и вставить" мою функцию в свой код. Во-вторых, я хочу убедиться, что моя функция работает в той же среде, что и моя. Например, я могу представить, что я использую некоторую библиотеку, которой нет у технической команды, или у нее есть версия, которая отличается от версии, которую я использую.

ADDED

В качестве возможного решения я считаю следующее. Я запускаю процесс Python, который слушает сокет, принимает входящие строки, преобразует их в JSON, передает JSON в "опубликованную" функцию и возвращает выходной JSON в виде строки. Имеет ли это решение недостатки? Другими словами, хорошая идея "публиковать" функцию Python в качестве фонового процесса при прослушивании сокета?

4b9b3361

Ответ 1

У вас есть правильная идея с использованием сокета, но есть тонны фреймворков, которые делают именно то, что вы хотите. Как hleggs, я предлагаю вам проверить Flask для создания микросервиса, Это позволит другой команде размещать объекты JSON в HTTP-запросе в вашем фляжном приложении и получать объекты JSON обратно. Не требуется знание базовой системы или дополнительных требований!

Здесь шаблон для флеш-приложения, который отвечает и отвечает с помощью 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)

Изменить: встроенный мой код напрямую в соответствии с Peter Britain

Ответ 2

Мое понимание вашего вопроса сводится к следующему:

Как я могу поделиться библиотекой Python с остальной частью моей команды, которая может не использовать Python в противном случае?

И как я могу убедиться, что мой код и его зависимости будут выполняться командой получателей?

И что принимающая команда может легко установить вещи в любом месте?

Это простой вопрос без прямого ответа... поскольку вы только что упоминали, что это может быть интегрировано в некоторый веб-сервис, но вы не знаете фактическую платформу для этой службы.

Вы также спрашиваете:

В качестве возможного решения я считаю следующее. Я запускаю процесс Python, который слушает сокет, принимает входящие строки, преобразует их в JSON, передает JSON в "опубликованную" функцию и возвращает выходной JSON в виде строки. Имеет ли это решение недостатки? Другими словами, хорошая идея "публиковать" функцию Python в качестве фонового процесса при прослушивании сокета?

В самом простом случае и для начала я бы сказал нет вообще. Запуск сетевых серверов, таких как HTTP-сервер (который встроен в Python), очень просто. Но сервис (даже если он квалифицирован как "микро" ) означает инфраструктуру, означает безопасность и т.д.

  • Что делать, если ожидаемый порт недоступен на машине развертывания? - Что происходит при перезагрузке этой машины?
  • Как ваш сервер запустится или перезагрузится, когда произойдет сбой?
  • Вам также понадобилось бы в конечном итоге предоставить услугу выскочки или systemd (в Linux)?
  • Будет ли ваш простой сокет или веб-сервер поддерживать несколько одновременных запросов?
  • существует ли риск безопасности для сокета?

Etc и т.д. При развертывании мой опыт работы с "простыми" серверами сокетов заключается в том, что в конечном итоге они не так просты.

В большинстве случаев будет проще избежать перераспределения службы сокетов в первую очередь. И предлагаемый подход здесь может быть использован для более полного пакета пакета на более позднем этапе, если вы хотите.

Вместо этого я предлагаю простой интерфейс командной строки, прекрасно упакованный для установки.

Минимальный набор вещей, которые следует учитывать, будет следующим:

  • предоставляют переносимый механизм для вызова вашей функции на многих ОС.
  • убедитесь, что вы упаковываете свою функцию таким образом, чтобы ее можно было установить со всеми правильными зависимостями
  • упростить установку и, конечно же, предоставить некоторые документы!

Шаг 1. Простейшим общим знаменателем будет предоставление интерфейса командной строки, который принимает путь к файлу JSON и накладывает JSON на stdout. Это будет работать на Linux, Mac и Windows.

Инструкции здесь должны работать на Linux или Mac и нуждаться в небольшой настройке для Windows (только для configure.sh script ниже)

Минимальным Python script может быть:

#!/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()

В конечном итоге вы можете обрабатывать большие входы, передавая путь к файлу JSON.

Шаг 2. Пакет вашей функции. В Python это достигается путем создания setup.py script. Это также касается установки любого зависимого кода из Pypi. Это гарантирует, что версия библиотек, на которую вы полагаетесь, - это те, которые вы ожидаете. Здесь я добавил nltk в качестве примера для зависимости. Добавьте ваш: это может быть scikit-learn, pandas, numpy и т.д. Этот setup.py также автоматически создает bin/predict script, который будет вашим основным интерфейсом командной строки:

#!/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']}
)

Кроме того, как это принято в Python, и чтобы упростить код установки, я создал каталог "Python package", перемещающий предиктор внутри этого каталога.

Шаг 3. Теперь вы хотите упаковать вещи, которые легко установить. Простой configure.sh script выполняет эту работу. Он устанавливает virtualenv, pip и setuptools, затем создает virtualenv в том же каталоге, что и ваш проект, а затем устанавливает ваш инструмент прогнозирования там (pip install . по существу совпадает с python setup.py install). С помощью этого script вы убедитесь, что код, который будет запущен, - это код, который вы хотите запустить с правильными зависимостями. Кроме того, вы гарантируете, что это изолированная установка с минимальными зависимостями и воздействием на целевую систему. Это проверено с помощью Python 2, но должно работать и на 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>"

В конце у вас есть полностью сконфигурированная, изолированная и простая в установке часть кода с простым переносимым интерфейсом командной строки. Вы можете увидеть все это в этом небольшом репо: https://github.com/pombredanne/predictorВы просто клонируете или получаете zip или tarball репо, затем проходите README, и вы находитесь в бизнесе.

Обратите внимание, что для более привлекательного способа для более сложных приложений, в том числе для обеспечения доступности зависимостей для легкой установки и не зависит от сети, вы можете проверить это https://github.com/nexB/scancode-toolkit Я тоже поддерживаю.

И если вы действительно хотите открыть веб-службу, вы можете повторно использовать этот подход и пакет, используя простой веб-сервер (например, встроенный в стандартную библиотеку Python или флакон или фляжку или gunicorn) и предоставить configure.sh, чтобы установить все это и создать командную строку для ее запуска.

Ответ 3

Ваша задача (в общем) о создании модели машинного обучения, где потребитель модели может не работать в той же среде, которая была использована для разработки модели. Я пытаюсь решить эту проблему с прошлых нескольких лет. Проблема сталкивается со многими компаниями, и она усугубляется из-за несоответствия навыков, целей, а также среды (языков, времени выполнения) между учеными-разработчиками данных и разработчиками. По моему опыту, доступны следующие решения/варианты, каждый из которых имеет свои уникальные преимущества и недостатки.

  • Вариант 1. Создайте часть прогноза своей модели как автономную веб-службу, используя любой легкий инструмент в Python (например, Flask). Вы должны попытаться как можно больше отделить часть разработки/обучения и прогнозирования модели. Модель, которую вы разработали, должна быть сериализована в некоторой форме, чтобы веб-сервер мог ее использовать.

    • Как часто обновляется модель обучения в машине? Если это делается не очень часто, сериализованный файл модели (пример: файл пиренейского питона) можно сохранить в общем месте, доступном для веб-сервера (скажем, s3), загруженного в память. Автономный веб-сервер должен предлагать API для прогнозирования.
    • Обратите внимание, что разоблачение одного предсказания модели с использованием Flask было бы простым. Но при необходимости масштабируя этот веб-сервер, при необходимости настраивая его с нужным набором библиотек, аутентификация входящих запросов - это нетривиальные задачи. Вы должны выбрать этот маршрут, только если у вас есть команды разработчиков, готовые помочь с ними.

    • Если модель часто обновляется, версия файла модели будет хорошим вариантом. Таким образом, вы можете комбинировать поверх любой системы управления версиями, проверяя весь файл модели, если он не слишком велик. Веб-сервер может дезацинировать (pickle.load) этот файл при запуске/обновлении и преобразовать в объект Python, на который вы можете вызвать методы прогнозирования.

  • Вариант 2: используйте язык разметки интеллектуального моделирования. PMML был специально разработан для этой цели: интеллектуальный формат обмена данными, независимый от окружающей среды. Поэтому ученый-ученый может разработать модель, экспортировать ее в файл PMML. Веб-сервер, используемый для прогнозирования, может затем использовать PMML файл для выполнения прогнозов. Вы обязательно должны проверить проект открытого подсчета, который позволяет вам выставлять модели машинного обучения через REST API для развертывания моделей и создания прогнозов.

    • Плюсы: PMML - стандартизованный формат, открытый подсчет - это зрелый проект с хорошей историей развития.
    • Минусы: PMML может не поддерживать все модели. Открытый выигрыш в первую очередь полезен, если ваш технологический выбор платформы разработки - это JVM. Экспорт моделей машинного обучения с Python не является простым. Но R имеет хорошую поддержку для экспорта моделей в виде файлов PMML.
  • Вариант 3. Существуют некоторые поставщики, предлагающие специальные решения для этой проблемы. Вам придется оценить стоимость лицензирования, стоимость оборудования, а также стабильность предложений для этого маршрута.

Какой бы вариант вы ни выбрали, рассмотрите долгосрочные затраты на поддержку этого варианта. Если ваша работа является доказательством концептуального этапа, лучшим вариантом будет лучший веб-сервер на основе Python + серверы с маринованной моделью. Надеюсь, этот ответ поможет вам!

Ответ 4

Как уже было предложено в других ответах, лучшим вариантом было бы создание простой веб-службы. Помимо Flask вы можете попробовать bottle, который является очень тонким однофайльным веб-фреймворком. Ваш сервис может выглядеть так же просто, как:

from bottle import route, run, request

@route('/')
def index():
    return my_function(request.json)

run(host='0.0.0.0', port=8080)

Чтобы поддерживать среду с одинаковой проверкой virtualenv, чтобы создать изолированную среду для предотвращения конфликтов с уже установленными пакетами и pip для установки точной версии пакетов в виртуальную среду.

Ответ 5

Думаю, у вас есть 3 возможности:

  • преобразовать функцию python в функцию javascript:

Предполагая, что "техническая команда" использует Javascript для веб-сервиса, вы можете попытаться преобразовать свою функцию python непосредственно в функцию Javascript (которая будет очень легко интегрироваться на веб-странице), используя empythoned (на основе emscripten)

Плохая точка этого метода заключается в том, что каждый раз, когда вам нужно обновлять/обновлять свою функцию python, вам также нужно снова преобразовать в Javascript, а затем проверить и подтвердить, что функция продолжает работать.

  • простой сервер API + JQuery

Если метод преобразования невозможен, я согласен с @justin-bell, вы можете использовать FLASK

получение JSON в качестве входa > JSON в ваш параметр функции > запустить функцию python > преобразовать результат функции в JSON > выполнить результат JSON

Предполагая, что вы выбрали решение FLASK, "технической команде" нужно будет отправить асинхронный вызов. GET/POST, содержащий все аргументы как JSON obj, когда им нужно получить некоторый результат от вашей функции python.

  • сервер websocket + socket.io

Вы также можете воспользоваться поиском Websocket для отправки в webservice (посмотрите на флягу + websocket для вашей стороны и socket.io для веб-сервис.)

= > websocket действительно полезен, когда вам нужно нажимать/получать данные с низкой стоимостью и латентностью (или из) для большого количества пользователей (не уверен, что веб-раскладка будет лучше всего соответствовать вашим потребностям)

Привет