所有编程语言调用python方式,非命令行可以获取返回值,适合所有Python版本
目前为止,如java,go等编程语言调用python的主要方式是命令行调用或者利用python c api,jpython等方式进行调用,这些方式各有各自的缺陷,比如jpython只能试用特定python,命令行无法获得返回值等,为此我想到一个方法,及python调用python,暴露一个api,可以适合各种编程语言,切对于Python所以import都适用,直接先上代码了
from flask import request, jsonify, Flaskimport importlibimport inspectimport sysimport jsonapp = Flask(__name__)@app.route('/', methods=["POST"])def run_py(): # put application's code here 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) #moudle_name无实际作用 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) # 获取FullArgSpec对象 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 requestsimport jsondef add(a,b):a = 1b = 2return a+b,a,bdef 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 mainimport ( "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