python与java的交互

java与python的交互

写在之前

最近项目交付结束,正在总结年初到现在做的琐碎项目与学习时,发现了一个比较有意思的交互,即java与python两个系统之间的互相请求访问,虽然当时跟我对接的python小伙伴已离职,但还是需要好好记录一下这个知识点的,毕竟少见的跨系统开发。

需求描述

前端-java后台-python算法分析-java处理分析结果返回

大概就是这么一个情况,公司产品需要一个上万人排班(而且可能是多个上万人进行排班)的功能,但系统是基于java做的后台,公司的算法那工程师使用的是python进行算法实现,故需要进行跨系统支持,毕竟算法运算非常非常吃资源

具体开发

因为是跨系统,故给算法python单独准备了一台机器,测试配备以10G+200G+4vCPU机器,python程序为打包程序,需要主动请求访问才会进行运算,并生成对应的结果文件等。

1.java后台的开发

1.1java请求python
1.首先,我们需要保证服务能远程到python服务器去访问执行算法分析。
  那么,需要进行远程操作:
  采用的是JSCH技术,通过ip端口进行访问,这里如果需要加密,不是内部环境,则需要进行配置公钥与私钥,我这里为内部环境,不用考虑,故跳过公钥的询问:StrictHostKeyChecking=no
    JSch jsch = new JSch();
    Session session = jsch.getSession(serverName, serverIp, serverPort);
    session.setPassword(serverPwd);
    session.setConfig(SESSIONCONFIG, SESSIONCONFIGVALUE);
    session.setTimeout(timeout);
    session.connect();
  然后,session连接后创建channel:
    Channel channel = session.openChannel(SFTPCHANNELNAME);
    channel.connect();
  最后,设置编码:
    ChannelSftp = (ChannelSftp) channel;
    sftp.setFilenameEncoding(“UTF-8”);
2.然后,执行命令运行python。
  比如先定义一个需要执行的命令:
    String cmd = "nohup /home/" + python执行路径包名 + 与python约定的参数 + “ &”;
  解释:nohup 与 & 防中断,执行完等待结果即可,约定参数包含回调地址。
  定义完命令,下面就是要进行执行:
    ChannelExec exec = (ChannelExec) session.openChannel(“exec”);
    exec.setCommand(cmd);
    exec.setErrStream(System.err);
    exec.connect();
    Map channelSessionMap = new HashMap();
    channelSessionMap.put(exec, session);
  通过exec进行命令的输入执行。
  这里需要注意的是如果多并发进行,是需要做校验处理的,多个任务需要进行区分,那我们可以通过参数传入当前任务的key进行辨认,而在java程序中做一个全局容器进行存放,处理完则释放.
    channelMap.put(channelKey, channelSessionMap);
1.2 java接到python请求

上面我们说到java请求python进行运算,算是一个结束,另一个重要的地方就是接受python处理结果,这里不需要做太多约束,仅仅与python进行接口约束暴露给python请求即可。

2.python请求java的开发

python在接到请求后读取参数,执行算法计算结果后返回。

这里python调用java推荐有两种方式:
1.requests:
引入requests:
  import requests, json, sys
这里的json为请求需要发送json格式的请求,sys为读取java请求过来的参数:
  post_url = sys.argv[1]
  userId = sys.argv[2]
  dateTime = sys.argv[3]
然后处理完结果后返回时需设置headers与请求参数:
  headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
  result_url = json.dumps({"userId": userId,
     "dateTime": dateTime,
     "resultFlag": "1",
     "file":"/home/resultFile.excel"
     })
最后定义请求方法调用即可:
def doPost():
    rsp = requests.post(post_url, result_url, headers=headers)

ps:**这里也许大家会有另一种写法,headers直接传参,并未进行赋值,这时会存在解析不到的问题,这个问题就需要将headers进行赋值。**

2.pycurl:
这种方式与requests类似,除了写法有些区别,其余基本无差:
依旧引入pycurl:
  import pycurl, json, sys
不多说,请求url与参数获取与requests一致,
headers的写法:
  headers = ["Content-Type:application/json;charset=utf-8"]
然后方法稍作变化:
  def test_post():
    c = pycurl.Curl()
    c.setopt(pycurl.HTTPHEADER, headers)
    c.setopt(pycurl.URL, post_url)
    c.setopt(pycurl.POST, 1)
    c.setopt(pycurl.POSTFIELDS, url_result)
    print(c.getinfo(pycurl.CONTENT_TYPE))
    c.perform()
    c.close()

这里说下requests与pycurl的选择:
1.如果请求服务器进行大量io操作使用requests。
2.如果请求需要消耗大量带宽(io频率低,但一次性网络传输数据量大),在不超带宽限制的情况下用pycurl。

code源码:https://github.com/lovezmming/spring-development-projects/tree/master/java2python
微信公众号:像是风
python与java的交互_第1张图片

你可能感兴趣的:(跨平台,java与pthon,java调用python,python调用java)