目前为止,如java,go等编程语言调用python的主要方式是命令行调用或者利用python c api,jpython等方式进行调用,这些方式各有各自的缺陷,比如jpython只能试用特定python,命令行无法获得返回值等,为此我想到一个方法,及python调用python,暴露一个api,可以适合各种编程语言,切对于Python所以import都适用,直接先上代码了
from flask import request, jsonify, Flask
import importlib
import inspect
import sys
import json
app = Flask(__name__)
@app.route('/', methods=["POST"])
def run_py():
data_list = []
data = json.loads(request.get_data(as_text=True))
method = data["method"]
path = data["path"]
type = data["type"]
args = data["args"]
sys_path = data["sys"]
for p in sys_path:
sys.path.append(p)
spec = importlib.util.spec_from_file_location("moudle_name", path)
odm = importlib.util.module_from_spec(spec)
spec.loader.exec_module(odm)
v_list = []
if hasattr(odm, method):
func = getattr(odm, method)
v_list = []
r = inspect.getfullargspec(func)
j = 0
for i in r.args:
if type == "map":
v_list.append(args[i])
elif type == "array":
v_list.append(args[j])
j = j + 1
res = func(*v_list)
return jsonify({"code": 200, "msg": "ok", "data": res})
if __name__ == '__main__':
app.run(host="127.0.0.1",port=5000)
该段代码有5个参数
- method:方法名字
- path:py文件路径
- args:python方法参数
- type:参数类型,支持map和array
- sys:依赖库地址,在Python使用虚拟环境时可以使用
接下来使用python写个简单demoo
import requests
import json
def add(a,b):
a = 1
b = 2
return a+b,a,b
def test():
url = "https://www.baidu.com"
response = requests.request("GET", url)
data=json.dumps({"test":"该方法只是为了测试有依赖情况下是否可以使用"})
return data
该py文件地址在/home/lihang/PycharmProjects/test/test.py
我们先使用postman测试一下 很明显成功了,接着使用各种编程语言尝试
Java
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n \"method\":\"test\",\n \"type\":\"map\",\n \"path\":\"/home/lihang/PycharmProjects/test/test.py\",\n \"args\":{\n },\n \"sys\":[]\n}");
Request request = new Request.Builder()
.url("http://127.0.0.1:5000/")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
Go
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "http://127.0.0.1:5000/"
method := "POST"
payload := strings.NewReader(`{
"method":"test",
"type":"map",
"path":"/home/lihang/PycharmProjects/test/test.py",
"args":{
},
"sys":[]
}`)
client := &http.Client {
}
req, err := http.NewRequest(method, url, payload)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/json")
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
bash
curl --location --request POST 'http://127.0.0.1:5000/' \
--header 'Content-Type: application/json' \
--data-raw '{
"method":"test",
"type":"map",
"path":"/home/lihang/PycharmProjects/test/test.py",
"args":{
},
"sys":[]
}'
Ruby
require "uri"
require "json"
require "net/http"
url = URI("http://127.0.0.1:5000/")
http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
request.body = JSON.dump({
"method": "test",
"type": "map",
"path": "/home/lihang/PycharmProjects/test/test.py",
"args": {},
"sys": []
})
response = http.request(request)
puts response.read_body
|