如何(以什么形式)共享(传递)一个 Python 功能?
How (in what form) to share (deliver) a Python function?
我工作的最终结果应该是一个 Python 函数,它将一个 JSON 对象作为唯一输入,return 另一个 JSON 对象作为输出。更具体地说,我是一名数据科学家,我所说的功能是从数据中派生出来的,它提供预测(换句话说,它是一个机器学习模型)。
所以,我的问题是如何将此功能传递给 "tech team" 并将其合并到 Web 服务中。
目前我遇到的问题很少。首先,技术团队不一定在 Python 环境中工作。所以,他们不能只 "copy and paste" 我的函数到他们的代码中。其次,我想确保我的函数运行在与我相同的环境中。例如,我可以想象我使用了一些技术团队没有的库,或者他们的版本与我使用的版本不同。
已添加
我考虑以下可能的解决方案。我启动了一个 Python 进程来侦听套接字,接受传入的字符串,将它们转换为 JSON,将 JSON 提供给 "published" 函数和 returns输出 JSON 作为字符串。这个解决方案有缺点吗?换句话说,将 "publish" 一个 Python 函数作为监听套接字的后台进程是个好主意吗?
您对使用套接字的想法是正确的,但是有大量的框架完全可以满足您的需求。喜欢 hleggs, I suggest you checkout Flask 构建微服务。这将让其他团队 post JSON 对象在 HTTP 请求中向您的烧瓶应用程序接收 JSON 对象。无需了解底层系统或其他要求!
这是一个使用 JSON
回复和响应的 Flask 应用程序模板
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的建议直接嵌入我的代码
我猜你有 3 种可能:
- 将python函数转换为javascript函数:
假设 "tech-team" 使用 Javascript 作为网络服务,您可以尝试将 python 函数直接转换为 Javascript 函数(这将非常容易集成到网页上)使用 empythoned (based on emscripten)
这种方法的缺点是每次你需要update/upgrade你的python函数时,你还需要再次转换为Javascript,然后检查并验证该函数继续工作。
- 简单API服务器+JQuery
如果转换方法不可行,我同意@justin-bell,你可以使用FLASK
获取 JSON 作为输入 > JSON 到你的函数参数 > 运行 python 函数 > 将函数结果转换为 JSON > 提供 JSON 结果
假设您选择 FLASK 解决方案,"tech-team" 将只需要发送一个异步。 GET/POST 请求包含所有参数作为 JSON obj,当它们需要从您的 python 函数中获得一些结果时。
- websocket 服务器 + socket.io
您还可以查看 Websocket 以分派到 web 服务(查看您这边的 flask + websocket 和 socket.io web 服务端。)
=> websocket 非常有用,当你需要 push/receive 低成本和低延迟的数据给(或来自)很多用户时 (不确定 websocket将最适合您的需要)
此致
您的任务(一般而言)是生产机器学习模型,其中模型的使用者可能与用于开发模型的环境不同。自过去几年以来,我一直在努力解决这个问题。许多公司都面临这个问题,而且由于数据科学家和开发人员之间的技能组合、目标和环境(语言,运行 时间)不匹配,问题变得更加严重。根据我的经验,以下 solutions/options 可用,每个都有其独特的优点和缺点。
选项 1:使用 Python 中的任何轻量级工具(例如 Flask ).您应该尽可能地解耦模型 development/training 和预测部分。您开发的模型必须序列化为某种形式,以便 Web 服务器可以使用它。
- 您的机器学习模型多久更新一次?如果不是经常这样做,可以将序列化模型文件(例如:Python pickle 文件)保存到 Web 服务器(例如 s3)可访问的公共位置,并加载到内存中。独立网络服务器应提供用于预测的 API。
请注意,使用 Flask 公开单个模型预测会很简单。但是如果需要扩展这个 web 服务器,用正确的库配置它,传入请求的身份验证都是非常重要的任务。只有当你有开发团队准备好帮助解决这些问题时,你才应该选择这条路线。
如果模型经常更新,对模型文件进行版本控制将是一个不错的选择。所以实际上,如果它不是太大,您可以通过签入整个模型文件来搭载在任何版本控制系统之上。 Web 服务器可以反序列化 (pickle.load) 此文件 startup/update 并转换为 Python 对象,您可以在该对象上调用预测方法。
选项 2:使用 predictive modeling markup language. PMML was developed specifically for this purpose: predictive modeling data interchange format independent of environment. So data scientist can develop model, export it to a PMML file. The web server used for prediction can then consume the PMML file for doing predictions. You should definitely check the open scoring project,它允许您通过 REST API 公开机器学习模型以部署模型和进行预测。
- 优点:PMML是标准化格式,开放评分是一个成熟的项目,具有良好的发展历史。
- 缺点:PMML 可能不支持所有模型。如果您的技术团队选择的开发平台是 JVM,则开放评分主要有用。从 Python 导出机器学习模型并不简单。但是 R 对将模型导出为 PMML 文件有很好的支持。
- 选项3:有some vendors offering dedicated solutions for this problem。您将必须评估许可成本、硬件成本以及采取这条路线的产品的稳定性。
无论您选择哪个选项,请考虑支持该选项的长期成本。如果您的工作处于概念验证阶段,Python 基于 Flask 的 Web 服务器 + 腌制模型文件将是最佳途径。希望这个回答对你有帮助!
正如其他答案中已经建议的那样,最好的选择是创建一个简单的 Web 服务。除了 Flask,您可能还想尝试 bottle,这是一个非常薄的单文件 Web 框架。您的服务可能看起来很简单:
from bottle import route, run, request
@route('/')
def index():
return my_function(request.json)
run(host='0.0.0.0', port=8080)
为了保持环境相同,请检查 virtualenv to make isolated environment for avoiding conflicts with already installed packages and pip 以将确切版本的软件包安装到虚拟环境中。
我对你的问题的理解归结为:
如何与我的团队其他成员共享 Python 库,否则他们可能不会使用 Python?
我如何确保我的代码及其依赖项符合接收团队的要求运行?
而且接收团队几乎可以在任何地方轻松安装东西?
这是一个简单的问题,没有直接的答案...正如您刚才提到的,这可能集成在某些网络服务中,但您不知道该服务的实际平台。
你还问:
As a possible solution I consider the following. I start a Python process that listen to a socket, accept incoming strings, transforms them into JSON, gives the JSON to the "published" function and returns the output JSON as a string. Does this solution have disadvantages? In other words, is it a good idea to "publish" a Python function as a background process listening to a socket?
在最简单的情况下,对于开始,我通常会说 no。启动网络服务器,例如 HTTP 服务器(内置 Python)非常容易。但是服务(即使符合"micro")意味着基础设施,意味着安全等。
- 如果您期望的端口在部署计算机上不可用怎么办? - 重启机器后会发生什么?
- 当出现故障时,您的服务器将如何启动或重启?
- 您是否还需要最终提供 upstart 或 systemd 服务(在 Linux 上)?
- 您的简单套接字或 Web 服务器是否支持多个并发请求?
- 公开套接字是否存在安全风险?
等等等等。部署时,我对"simple"套接字服务器的经验是,它们最终并不是那么简单。
在大多数情况下,首先避免重新分配套接字服务会更简单。如果您愿意,此处提出的方法可用于在稍后阶段以更简单的方式打包整个服务。
我建议的是简单的命令行界面,为安装精心打包。
需要考虑的最少事项是:
- 提供一种可移植的机制来在许多操作系统上调用您的函数
- 确保打包您的函数,以便它可以与所有正确的依赖项一起安装
- 使其易于安装,当然还提供一些文档!
第 1 步。 最简单的共同点是提供一个命令行界面,该界面接受 JSON 文件的路径并在 JSON标准输出。
这将在 Linux、Mac 和 Windows 上 运行。
此处的说明适用于 Linux 或 Mac,需要对 Windows 稍作调整(仅适用于更下方的 configure.sh
脚本)
最小的 Python 脚本可以是:
#!/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
脚本来实现的。这也负责从 Pypi 安装任何依赖代码。这将确保您所依赖的库版本是您期望的版本。在这里,我添加了 nltk
作为依赖项的示例。添加您的:这可能是 scikit-learn
、pandas
、numpy
等。此 setup.py
还会自动创建一个 bin/predict
脚本,它将成为您的主要命令行界面:
#!/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
脚本就可以完成这项工作。它安装 virtualenv
、pip
和 setuptools
,然后在与您的项目相同的目录中创建一个 virtualenv
,然后在其中安装您的预测工具(pip install .
是与 python setup.py install
基本相同)。使用此脚本,您可以确保 运行 的代码是您希望 运行 具有正确依赖关系的代码。此外,您确保这是一个独立的安装,对目标系统的依赖性和影响最小。这是用 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,然后浏览自述文件即可。
请注意,对于更复杂的应用程序,包括出售依赖项以便于安装而不依赖于网络,您可以查看这个 https://github.com/nexB/scancode-toolkit 我也维护。
如果你真的想公开一个 web 服务,你可以重用这个方法并将它与一个简单的 web 服务器打包(比如 Python 标准库或 bottle 或 flask 中内置的服务器或gunicorn) 并提供 configure.sh
来安装它并生成命令行来启动它。
我工作的最终结果应该是一个 Python 函数,它将一个 JSON 对象作为唯一输入,return 另一个 JSON 对象作为输出。更具体地说,我是一名数据科学家,我所说的功能是从数据中派生出来的,它提供预测(换句话说,它是一个机器学习模型)。
所以,我的问题是如何将此功能传递给 "tech team" 并将其合并到 Web 服务中。
目前我遇到的问题很少。首先,技术团队不一定在 Python 环境中工作。所以,他们不能只 "copy and paste" 我的函数到他们的代码中。其次,我想确保我的函数运行在与我相同的环境中。例如,我可以想象我使用了一些技术团队没有的库,或者他们的版本与我使用的版本不同。
已添加
我考虑以下可能的解决方案。我启动了一个 Python 进程来侦听套接字,接受传入的字符串,将它们转换为 JSON,将 JSON 提供给 "published" 函数和 returns输出 JSON 作为字符串。这个解决方案有缺点吗?换句话说,将 "publish" 一个 Python 函数作为监听套接字的后台进程是个好主意吗?
您对使用套接字的想法是正确的,但是有大量的框架完全可以满足您的需求。喜欢 hleggs, I suggest you checkout Flask 构建微服务。这将让其他团队 post JSON 对象在 HTTP 请求中向您的烧瓶应用程序接收 JSON 对象。无需了解底层系统或其他要求!
这是一个使用 JSON
回复和响应的 Flask 应用程序模板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的建议直接嵌入我的代码
我猜你有 3 种可能:
- 将python函数转换为javascript函数:
假设 "tech-team" 使用 Javascript 作为网络服务,您可以尝试将 python 函数直接转换为 Javascript 函数(这将非常容易集成到网页上)使用 empythoned (based on emscripten)
这种方法的缺点是每次你需要update/upgrade你的python函数时,你还需要再次转换为Javascript,然后检查并验证该函数继续工作。
- 简单API服务器+JQuery
如果转换方法不可行,我同意@justin-bell,你可以使用FLASK
获取 JSON 作为输入 > JSON 到你的函数参数 > 运行 python 函数 > 将函数结果转换为 JSON > 提供 JSON 结果
假设您选择 FLASK 解决方案,"tech-team" 将只需要发送一个异步。 GET/POST 请求包含所有参数作为 JSON obj,当它们需要从您的 python 函数中获得一些结果时。
- websocket 服务器 + socket.io
您还可以查看 Websocket 以分派到 web 服务(查看您这边的 flask + websocket 和 socket.io web 服务端。)
=> websocket 非常有用,当你需要 push/receive 低成本和低延迟的数据给(或来自)很多用户时 (不确定 websocket将最适合您的需要)
此致
您的任务(一般而言)是生产机器学习模型,其中模型的使用者可能与用于开发模型的环境不同。自过去几年以来,我一直在努力解决这个问题。许多公司都面临这个问题,而且由于数据科学家和开发人员之间的技能组合、目标和环境(语言,运行 时间)不匹配,问题变得更加严重。根据我的经验,以下 solutions/options 可用,每个都有其独特的优点和缺点。
选项 1:使用 Python 中的任何轻量级工具(例如 Flask ).您应该尽可能地解耦模型 development/training 和预测部分。您开发的模型必须序列化为某种形式,以便 Web 服务器可以使用它。
- 您的机器学习模型多久更新一次?如果不是经常这样做,可以将序列化模型文件(例如:Python pickle 文件)保存到 Web 服务器(例如 s3)可访问的公共位置,并加载到内存中。独立网络服务器应提供用于预测的 API。
请注意,使用 Flask 公开单个模型预测会很简单。但是如果需要扩展这个 web 服务器,用正确的库配置它,传入请求的身份验证都是非常重要的任务。只有当你有开发团队准备好帮助解决这些问题时,你才应该选择这条路线。
如果模型经常更新,对模型文件进行版本控制将是一个不错的选择。所以实际上,如果它不是太大,您可以通过签入整个模型文件来搭载在任何版本控制系统之上。 Web 服务器可以反序列化 (pickle.load) 此文件 startup/update 并转换为 Python 对象,您可以在该对象上调用预测方法。
选项 2:使用 predictive modeling markup language. PMML was developed specifically for this purpose: predictive modeling data interchange format independent of environment. So data scientist can develop model, export it to a PMML file. The web server used for prediction can then consume the PMML file for doing predictions. You should definitely check the open scoring project,它允许您通过 REST API 公开机器学习模型以部署模型和进行预测。
- 优点:PMML是标准化格式,开放评分是一个成熟的项目,具有良好的发展历史。
- 缺点:PMML 可能不支持所有模型。如果您的技术团队选择的开发平台是 JVM,则开放评分主要有用。从 Python 导出机器学习模型并不简单。但是 R 对将模型导出为 PMML 文件有很好的支持。
- 选项3:有some vendors offering dedicated solutions for this problem。您将必须评估许可成本、硬件成本以及采取这条路线的产品的稳定性。
无论您选择哪个选项,请考虑支持该选项的长期成本。如果您的工作处于概念验证阶段,Python 基于 Flask 的 Web 服务器 + 腌制模型文件将是最佳途径。希望这个回答对你有帮助!
正如其他答案中已经建议的那样,最好的选择是创建一个简单的 Web 服务。除了 Flask,您可能还想尝试 bottle,这是一个非常薄的单文件 Web 框架。您的服务可能看起来很简单:
from bottle import route, run, request
@route('/')
def index():
return my_function(request.json)
run(host='0.0.0.0', port=8080)
为了保持环境相同,请检查 virtualenv to make isolated environment for avoiding conflicts with already installed packages and pip 以将确切版本的软件包安装到虚拟环境中。
我对你的问题的理解归结为:
如何与我的团队其他成员共享 Python 库,否则他们可能不会使用 Python?
我如何确保我的代码及其依赖项符合接收团队的要求运行?
而且接收团队几乎可以在任何地方轻松安装东西?
这是一个简单的问题,没有直接的答案...正如您刚才提到的,这可能集成在某些网络服务中,但您不知道该服务的实际平台。
你还问:
As a possible solution I consider the following. I start a Python process that listen to a socket, accept incoming strings, transforms them into JSON, gives the JSON to the "published" function and returns the output JSON as a string. Does this solution have disadvantages? In other words, is it a good idea to "publish" a Python function as a background process listening to a socket?
在最简单的情况下,对于开始,我通常会说 no。启动网络服务器,例如 HTTP 服务器(内置 Python)非常容易。但是服务(即使符合"micro")意味着基础设施,意味着安全等。
- 如果您期望的端口在部署计算机上不可用怎么办? - 重启机器后会发生什么?
- 当出现故障时,您的服务器将如何启动或重启?
- 您是否还需要最终提供 upstart 或 systemd 服务(在 Linux 上)?
- 您的简单套接字或 Web 服务器是否支持多个并发请求?
- 公开套接字是否存在安全风险?
等等等等。部署时,我对"simple"套接字服务器的经验是,它们最终并不是那么简单。
在大多数情况下,首先避免重新分配套接字服务会更简单。如果您愿意,此处提出的方法可用于在稍后阶段以更简单的方式打包整个服务。
我建议的是简单的命令行界面,为安装精心打包。
需要考虑的最少事项是:
- 提供一种可移植的机制来在许多操作系统上调用您的函数
- 确保打包您的函数,以便它可以与所有正确的依赖项一起安装
- 使其易于安装,当然还提供一些文档!
第 1 步。 最简单的共同点是提供一个命令行界面,该界面接受 JSON 文件的路径并在 JSON标准输出。 这将在 Linux、Mac 和 Windows 上 运行。
此处的说明适用于 Linux 或 Mac,需要对 Windows 稍作调整(仅适用于更下方的 configure.sh
脚本)
最小的 Python 脚本可以是:
#!/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
脚本来实现的。这也负责从 Pypi 安装任何依赖代码。这将确保您所依赖的库版本是您期望的版本。在这里,我添加了 nltk
作为依赖项的示例。添加您的:这可能是 scikit-learn
、pandas
、numpy
等。此 setup.py
还会自动创建一个 bin/predict
脚本,它将成为您的主要命令行界面:
#!/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
脚本就可以完成这项工作。它安装 virtualenv
、pip
和 setuptools
,然后在与您的项目相同的目录中创建一个 virtualenv
,然后在其中安装您的预测工具(pip install .
是与 python setup.py install
基本相同)。使用此脚本,您可以确保 运行 的代码是您希望 运行 具有正确依赖关系的代码。此外,您确保这是一个独立的安装,对目标系统的依赖性和影响最小。这是用 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,然后浏览自述文件即可。
请注意,对于更复杂的应用程序,包括出售依赖项以便于安装而不依赖于网络,您可以查看这个 https://github.com/nexB/scancode-toolkit 我也维护。
如果你真的想公开一个 web 服务,你可以重用这个方法并将它与一个简单的 web 服务器打包(比如 Python 标准库或 bottle 或 flask 中内置的服务器或gunicorn) 并提供 configure.sh
来安装它并生成命令行来启动它。