用其他语言调用Python模块,并提高模块的导入速度

现在许多的项目都要求实时性,如果直接用Java中的Runtime调用命令行界面中的python函数,则在运行python文件前每次都得重新导入对应的包,导致函数运行的时间格外地长。在最初没经过优化的时候大概每次执行函数都需要10多秒的时间。这样远远不能够满足在界面调用的时候实时性要求。

最开始的想法是对python中的运行效率进行了极致优化,例如将jieba换成jieba_fast,砍除所有用不到的功能,对数据处理的结构,循环结构,变量使用进行了优化,使对应执行的效率大大提高,然而这个过程费力不讨好,经过了一系列优化之后,最终使Java中执行python函数的时间缩短至4秒多。4秒多,虽然在运行过程中可以等待一小段时间,但这样一来的话,如果要调用的函数次数一多,经过的时间也是漫长的,同时,用户的体验也不佳。

经过对python中的结构进行分析了之后,优化到极致之后调用对应函数时间长的原因主要在于import对应包的阶段,而这个过程并不能通过优化来使时间缩短。

例如,导入包

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import scipy.ndimage
import scipy.signal
import sys
import os

下面是导入包需要的时间:

matplotlib.pyplot   [300ms]
numpy               [110ms]
scipy.signal        [200ms]

通过不断地搜索,发现可以用socket套接字编程来解决这个问题,将python上对应的接口转化为Server,利用client来访问Server上的接口,这样一来就不用反复import对应的包名了。

服务器端:

创建文件server.py

# -- coding:utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import scipy.ndimage
import scipy.signal
import sys
import os

import socket

End='end send' #这里是为了判断对应的客户端请求命令的结束标志,目的是为了接受不超过8192个字符的(client)客户端请求。
def recv_end(the_socket):
    total_data=[]
    while True:
        data=the_socket.recv(8192).decode('utf-8')
        print('1: ' + data)
        if End in data:
            total_data.append(data[:data.find(End)]) # 取'end send'前面的字段
            print( total_data)
            break
        total_data.append(data)
        if len(total_data)>1:
            #check if end_of_data was split
            last_pair=total_data[-2]+total_data[-1]
            print( last_pair)
            if End in last_pair:
                total_data[-2]=last_pair[:last_pair.find(End)]
                total_data.pop()
                print( total_data)
                break
    return ''.join(total_data)

HOST = ''                 # Symbolic name meaning all available interfaces
PORT = 50007              # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
while 1:
    conn, addr = s.accept()
    print('Connected by', addr) # e.g., Connected by ('127.0.0.1', 13917)

    data=recv_end(conn) # 接受客服端发送过来的数据,并进行处理
    method = data[0]
    subdata = data[1:]

    if (method == "1"): #当客户端传递过来的第一个字符为1时,params表示传递过来的参数
        params=subdata.split("|")
        #这里写要调用的函数

        #将结果返回给客户端
        conn.sendall((str((params[0],params[1]))).encode()) # 发送给客户端
    #elif method=='2': #当客户端传递过来的第一个字符为2时
    #   #需要执行的命令2

    # update plot
    # data = conn.recv(1024)
    # if not data: break
    # conn.sendall(("PLOTTING:" + str(data)).encode())
    # update plot
    conn.close()

客户端:

创建文件client.py

# -- coding:utf-8 -*-
#调用服务端接口客户端,以缩短调用时间

import socket
import sys

HOST = '127.0.0.1'  # The remote host
#HOST = ''  # The remote host
PORT = 50007  # The same port as used by the server

End='end send'

def cl_test(test1,test2):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    s.sendall((str(1)+ test1+"|"+test2 +End).encode()) #str(1)表示第一个字符,然后在server端中规定字符串用|隔开

    data = []
    while True:
        subdata = s.recv(20480) #接受服务端返回参数
        if not subdata: break
        data.append(str(subdata, encoding='utf-8'))
    data = ''.join(data)

    s.close()
    return data #data是服务端的返回参数

print( 'Received', repr(cl_test('wode','nide ne ')))

运行流程:

(1)首先开启服务端:

python server.py

开启后,服务器端等待接收数据。

(2)启动客户端:

python client.py

客户端接收到服务器端发送回来的数据后,自动结束。

(3)服务器端显示的数据:

服务器端一直在运行状态,未结束。

 

最后Socket相关函数和连接过程,请参见https://www.cnblogs.com/wumingxiaoyao/p/7047658.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值