未验证 提交 ee57795b 编写于 作者: W Wang Guibao 提交者: GitHub

Merge pull request #69 from wangguibao/python_client

Add python & PHP demo to access HTTP Interface
...@@ -77,6 +77,10 @@ install(TARGETS echo ...@@ -77,6 +77,10 @@ install(TARGETS echo
RUNTIME DESTINATION ${PADDLE_SERVING_INSTALL_DIR}/demo/client/echo/bin) RUNTIME DESTINATION ${PADDLE_SERVING_INSTALL_DIR}/demo/client/echo/bin)
install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/conf DESTINATION install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/conf DESTINATION
${PADDLE_SERVING_INSTALL_DIR}/demo/client/echo/) ${PADDLE_SERVING_INSTALL_DIR}/demo/client/echo/)
install(FILES ${CMAKE_CURRENT_LIST_DIR}/python/echo.py
DESTINATION ${PADDLE_SERVING_INSTALL_DIR}/demo/client/echo/python)
install(FILES ${CMAKE_CURRENT_LIST_DIR}/php/echo.php
DESTINATION ${PADDLE_SERVING_INSTALL_DIR}/demo/client/echo/php)
install(TARGETS echo_kvdb install(TARGETS echo_kvdb
RUNTIME DESTINATION ${PADDLE_SERVING_INSTALL_DIR}/demo/client/echo_kvdb/bin) RUNTIME DESTINATION ${PADDLE_SERVING_INSTALL_DIR}/demo/client/echo_kvdb/bin)
...@@ -108,6 +112,14 @@ install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/conf DESTINATION ...@@ -108,6 +112,14 @@ install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/conf DESTINATION
${PADDLE_SERVING_INSTALL_DIR}/demo/client/text_classification/) ${PADDLE_SERVING_INSTALL_DIR}/demo/client/text_classification/)
install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/data/text_classification DESTINATION install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/data/text_classification DESTINATION
${PADDLE_SERVING_INSTALL_DIR}/demo/client/text_classification/data) ${PADDLE_SERVING_INSTALL_DIR}/demo/client/text_classification/data)
install(FILES ${CMAKE_CURRENT_LIST_DIR}/python/text_classification.py
DESTINATION
${PADDLE_SERVING_INSTALL_DIR}/demo/client/text_classification/python)
install(FILES ${CMAKE_CURRENT_LIST_DIR}/php/text_classification.php
DESTINATION
${PADDLE_SERVING_INSTALL_DIR}/demo/client/text_classification/php)
install(TARGETS ctr_prediction install(TARGETS ctr_prediction
RUNTIME DESTINATION RUNTIME DESTINATION
......
<?
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
function http_post($url, $data) {
// array to json string
$data_string = json_encode($data);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
// post data 封装
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
// true是获取文本,不直接输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 强制curl不使用100-continue
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
// set header
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data_string))
);
// 执行
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
//key value 数组,如果多,后面用逗号分开key =>value ,key1 => value1 ,....
echo http_post('http://127.0.0.1:8010/BuiltinTestEchoService/inference', array("a" => 1, "b" => 0.5));
?>
<?
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
define(BATCH_SIZE, "10");
function read_data($data_file, &$samples, &$labels) {
$handle = fopen($data_file, "r");
$search = array("(", ")", "[", "]");
$count = 0;
while (($buffer = fgets($handle)) !== false) {
$count++;
$buffer = str_ireplace($search, "", $buffer);
$x = explode(",", $buffer);
$ids = array();
for ($i = 0; $i < count($x); ++$i) {
$ids[] = (int)($x[$i]);
}
$label = array_slice($ids, count($ids) - 1);
$sample = array_slice($ids, 0, count($ids) - 1);
$samples[] = array("ids" => $sample);
$labels[] = $label;
unset($x);
unset($buffer);
unset($ids);
unset($sample);
unset($label);
}
if (!feof($handle)) {
echo "Unexpected fgets() fail";
return -1;
}
fclose($handle);
}
function &http_connect($url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
// true是获取文本,不直接输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 强制curl不使用100-continue
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
// set header
curl_setopt($ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json'
)
);
return $ch;
}
function http_post(&$ch, $data) {
// array to json string
$data_string = json_encode($data);
// post data 封装
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
// set header
curl_setopt($ch,
CURLOPT_HTTPHEADER,
array(
'Content-Length: ' . strlen($data_string)
)
);
// 执行
$result = curl_exec($ch);
return $result;
}
if ($argc != 2) {
echo "Usage: php text_classification.php DATA_SET_FILE\n";
return -1;
}
ini_set('memory_limit', '-1');
$samples = array();
$labels = array();
read_data($argv[1], $samples, $labels);
echo count($samples) . "\n";
$ch = &http_connect('http://127.0.0.1:8010/TextClassificationService/inference');
$count = 0;
for ($i = 0; $i < count($samples) - BATCH_SIZE; $i += BATCH_SIZE) {
$instances = array_slice($samples, $i, BATCH_SIZE);
echo http_post($ch, array("instances" => $instances)) . "\n";
}
curl_close($ch);
?>
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import urllib2
data = {"a": 1, "b": 0.5}
request_json = json.dumps(data)
req = urllib2.Request("http://127.0.0.1:8010/BuiltinTestEchoService/inference")
try:
response = urllib2.urlopen(req, request_json, 1)
print response.read()
except urllib2.HTTPError as e:
print e.reason
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import httplib
import sys
import os
BATCH_SIZE = 10
def data_reader(data_file, samples, labels):
if not os.path.exists(data_file):
print "Path %s not exist" % data_file
return -1
with open(data_file, "r") as f:
for line in f:
line = line.replace('(', ' ')
line = line.replace(')', ' ')
line = line.replace('[', ' ')
line = line.replace(']', ' ')
ids = line.split(',')
ids = [int(x) for x in ids]
label = ids[-1]
ids = ids[0:-1]
samples.append(ids)
labels.append(label)
if __name__ == "__main__":
""" main
"""
if len(sys.argv) != 2:
print "Usage: python text_classification.py DATA_FILE"
sys.exit(-1)
samples = []
labels = []
ret = data_reader(sys.argv[1], samples, labels)
conn = httplib.HTTPConnection("127.0.0.1", 8010)
for i in range(0, len(samples) - BATCH_SIZE, BATCH_SIZE):
batch = samples[i:i + BATCH_SIZE]
ids = []
for x in batch:
ids.append({"ids": x})
ids = {"instances": ids}
request_json = json.dumps(ids)
try:
conn.request('POST', "/TextClassificationService/inference",
request_json, {"Content-Type": "application/json"})
response = conn.getresponse()
print response.read()
except httplib.HTTPException as e:
print e.reason
# HTTP Inferface
Paddle Serving服务均可以通过HTTP接口访问,客户端只需按照Service定义的Request消息格式构造json字符串即可。客户端构造HTTP请求,将json格式数据以POST请求发给serving端,serving端**自动**按Service定义的Protobuf消息格式,将json数据转换成protobuf消息。
本文档介绍以python和PHP语言访问Serving的HTTP服务接口的用法。
## 1. 访问地址
访问Serving节点的HTTP服务与C++服务使用同一个端口(例如8010),访问URL规则为:
```
http://127.0.0.1:8010/ServiceName/inference
http://127.0.0.1:8010/ServiceName/debug
```
其中ServiceName应该与Serving的配置文件`conf/services.prototxt`中配置的一致,假如有如下2个service:
```protobuf
services {
name: "BuiltinTestEchoService"
workflows: "workflow3"
}
services {
name: "TextClassificationService"
workflows: "workflow6"
}
```
则访问上述2个Serving服务的HTTP URL分别为:
```
http://127.0.0.1:8010/BuiltinTestEchoService/inference
http://127.0.0.1:8010/BuiltinTestEchoService/debug
http://127.0.0.1:8010/TextClassificationService/inference
http://127.0.0.1:8010/TextClassificationService/debug
```
## 2. Python访问HTTP Serving
Python语言访问HTTP Serving,关键在于构造json格式的请求数据,可以通过以下步骤完成:
1) 按照Service定义的Request消息格式构造python object
2) `json.dump()` / `json.dumps()` 等函数将python object转换成json格式字符串
以TextClassificationService为例,关键代码如下:
```python
# Connect to server
conn = httplib.HTTPConnection("127.0.0.1", 8010)
# samples是一个list,其中每个元素是一个ids字典:
# samples[0] = [190, 1, 70, 382, 914, 5146, 190...]
for i in range(0, len(samples) - BATCH_SIZE, BATCH_SIZE):
# 构建批量预测数据
batch = samples[i: i + BATCH_SIZE]
ids = []
for x in batch:
ids.append({"ids" : x})
ids = {"instances": ids}
# python object转成json
request_json = json.dumps(ids)
# 请求HTTP服务,打印response
try:
conn.request('POST', "/TextClassificationService/inference", request_json, {"Content-Type": "application/json"})
response = conn.getresponse()
print response.read()
except httplib.HTTPException as e:
print e.reason
```
完整示例请参考[text_classification.py](demo-client/python/text_classification.py)
## 3. PHP访问HTTP Serving
PHP语言构造json格式字符串的步骤如下:
1) 按照Service定义的Request消息格式,构造PHP array
2) `json_encode()`函数将PHP array转换成json字符串
以TextCLassificationService为例,关键代码如下:
```PHP
function http_post(&$ch, $data) {
// array to json string
$data_string = json_encode($data);
// post data 封装
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
// set header
curl_setopt($ch,
CURLOPT_HTTPHEADER,
array(
'Content-Length: ' . strlen($data_string)
)
);
// 执行
$result = curl_exec($ch);
return $result;
}
$ch = &http_connect('http://127.0.0.1:8010/TextClassificationService/inference');
$count = 0;
# $samples是一个2层array,其中每个元素是一个如下array:
# $samples[0] = array(
# "ids" => array(
# [0] => int(190),
# [1] => int(1),
# [2] => int(70),
# [3] => int(382),
# [4] => int(914),
# [5] => int(5146),
# [6] => int(190)...)
# )
for ($i = 0; $i < count($samples) - BATCH_SIZE; $i += BATCH_SIZE) {
$instances = array_slice($samples, $i, BATCH_SIZE);
echo http_post($ch, array("instances" => $instances)) . "\n";
}
curl_close($ch);
```
完整代码请参考[text_classification.php](demo-client/php/text_classification.php)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册