python request 接口链接带参_python reload报错


本文是一篇小白科普文。

作为一名算法工程师,不仅需要实现模型,而且需要了解一些工程方面的知识,比如别人如何请求我的代码?如何监控程序运行状态?一些比较重要的信息在传输中通过怎样的方式进行加密?如何告诉请求我接口的人我的算法程序已经运行完毕?本篇主要介绍这些简单的工程问题。

一、别人如何请求我的代码(即:如何用python开发自己的接口)

先直接给个示例代码:


from flask import Flask, jsonify
from flask import abort
from flask import request

app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False

def 我的算法模型_函数():
    *****
    return 我的算法模型_运行结果


# 接口部分
@app.route('/我随便定义的网址,比如Maria', methods=['POST'])
def 我定义的接口函数():
    #  本地测试 读取参数 
    if request.json:
        print("进来了")
        df_data_json = request.json['我模型的参数1']
        k_cluster = request.json['我模型的参数2']
        df_feature_maxmin_json = request.json['我模型的参数3']

    # 把传入的参数,代入“我的算法模型_函数”,得到“我的算法模型_运行结果”
    我的算法模型_运行结果 = 我的算法模型_函数(df_data_json, k_cluster, df_feature_maxmin_json)
    if len(我的算法模型_运行结果) > 1:
        result = 1  # succeed
    else:
        result = -1
    return jsonify({"result": result, "我的算法模型_运行结果": json.loads(我的算法模型_运行结果)})


if __name__ == '__main__':
    app.run(host="本机IP地址如192.168.32.432", port=自己定义的端口号如6666, debug=True)  # 本机测试


此时,其他人该如何请求我的接口呢?示例如下:


''' post数据, 请求接口 '''
# 先把模型需要的参数定义好
a = {"我模型的参数1": df_data_json, "我模型的参数2": k_cluster, "我模型的参数3": df_feature_maxmin_json}
r = requests.post("http://本机IP地址如192.168.32.432:自己定义的端口号如6666/我随便定义的网址,比如Maria", json=a)  # 本机测试

# 查看返回的“我的算法模型_运行结果”
aaa = r.content
bbb = aaa.decode()
print("返回的开头数据:", bbb[0:1000])
print("============== finish ==============")


=============以上就是一个完整的python接口开发和请求的过程啦=========

以下是原理科普,可以参考以下教程:

python实现RESTful服务(基于flask)

数据蛙datafrog:用Python 的Flask实现 RESTful API(学习篇)

二、如何监控程序运行状态以及保持运行?(即:supervisor用法)

我们需要把我们的“我的算法模型”保持运行的状态,这样其他人才可能随时调用我们的接口,得到“我的算法模型_运行结果”,如何保持运行状态并监控呢?我们引用一个工具“supervisor”。配置方法如下:


1. ### 下载包
pip3 install supervisor

2. ### 生成配置文件,且放在/etc目录下
echo_supervisord_conf > /etc/supervisord.conf 

3.### 为了不将所有新增配置信息全写在一个配置文件里,这里新建一个文件夹,每个程序设置一个配置文件,相互隔离
mkdir /etc/supervisord.d/  

4. ### 修改配置文件
vim /etc/supervisord.conf

5.### 加入以下配置信息
"[include]
files = /etc/supervisord.d/*.conf"

### 在supervisord.conf中设置通过web可以查看管理的进程,加入以下代码(默认即有,取消注释即可)  
"[inet_http_server] 
port=定义的IP:定义的端口号  "

[supervisorctl]         ; ### 在supervisord.conf中设置通过web可以查看管理的进程,加入以下代码(默认即有,取消注释即可)    
serverurl=http://定义的IP:定义的端口号 ; #定义的IP:定义的端口号

[supervisord]
user=root ; supervisord            ; setuid to this UNIX account at startup; recommended if root

6.启动supervisord
supervisorctl -c /etc/supervisord.conf


7. ### 以下即为配置文件中的内容
vim /etc/supervisord.d/supervisor_cluster.conf

[program:cluster]
command=python3 需运行的程序(带上程序放的位置_绝对路径).py   ; 被监控的进程路径
;autostart=true                ; 随着supervisord的启动而启动
autorestart=true              ; 自动重启。。当然要选上了

8.重启
supervisorctl reload
### 或者
supervisorctl -c /etc/supervisord.conf
reload
start all
status

9. ## 查看报错日志
vim /tmp/supervisord.log

-------------------------
10. ### 其他的一些命令
update 更新新的配置到supervisord(不会重启原来已运行的程序)	
reload,载入所有配置文件,并按新的配置启动、管理所有进程(会重启原来已运行的程序)	
start xxx: 启动某个进程	
restart xxx: 重启某个进程	
stop xxx: 停止某一个进程(xxx),xxx为[program:theprogramname]里配置的值	
stop groupworker: 重启所有属于名为groupworker这个分组的进程(start,restart同理)	
stop all,停止全部进程,注:start、restart、stop都不会载入最新的配置文	
reread,当一个服务由自动启动修改为手动启动时执行一下就ok


=============以上就是supervisor配置的过程啦=========

以下是原理科普,可以参考以下教程:

supervisor用法

三、一些比较重要的信息在传输中通过怎样的方式进行加密?(即:pyDes 加密解密)

对于传输的数据库的用户名、密码等,我们需要用加密的方式进行传输,可以采用DES加密解密的方式,示例如下:


def decode(cipher, DES_SECRET_KEY):
    '''
    # des模式  填充方式  CBC解密
    :param cipher:  密文 需要解密的 
    :param DES_SECRET_KEY: # 秘钥 之后需要截取前8位作为真实的密钥
    :return:
    '''
    # 偏移变量 这个固定不用改
    IV_PARAMETER = 'AI_MP'
    # 秘钥:截取前8位作为真实的密钥
    DES_SECRET_KEY = DES_SECRET_KEY[0:8]
    # 密钥字符串转字节码
    s = bytes(cipher, 'utf-8')
    # 初始化一个des对象,参数是秘钥,解密方式,偏移, 填充方式
    des_obj = des(DES_SECRET_KEY, CBC, IV_PARAMETER, padmode=PAD_PKCS5)
    # 解密
    password = des_obj.decrypt(base64.b64decode(s))
    # 打印真实数据
    # print("真实数据:", password.decode())
    return password.decode()


=============以上就是pyDes 加密解密的过程啦=========

以下是原理科普,可以参考以下教程:

pyDES实现DES加解密_我在浪里-CSDN博客_pydes

Python使用Crypto/pyDes,DES并Base64编码

四、如何告诉请求我接口的人我的算法程序已经运行完毕?(即:回调接口+rsa私钥加签)

rsa私钥加签(注意:rsajava是用的pkcs8编码,python是用的pkcs1编码,需要用openssl把pkcs8转成pkcs1):


def make_key():
    """
    生成公钥和私钥
    :return:
    """
    pub_key, pri_key = rsa.newkeys(1024)
    pub_pkcs = pub_key.save_pkcs1()
    pri_pkcs = pri_key.save_pkcs1()
    print('pub_pkcs:n' + pub_pkcs.decode())
    print('pri_pkcs:n' + pri_pkcs.decode())


def sign(path: str, msg: str) -> str:
    """
    对给定的字符串加签
    :param path: 私钥文件路径
    :param msg: 需要加签的字符串
    :return: 加签后的字符串
    """
    with open(path, 'r', encoding='utf-8') as f:
        pri_pkcs = f.read()
    print('私钥:n' + pri_pkcs)
    pri_key = rsa.PrivateKey.load_pkcs1(pri_pkcs.encode())
    result = rsa.sign(msg.encode(), pri_key, 'SHA-1')
    sign_str = b64encode(result).decode()
    return sign_str


def verify(path: str, sign_str: str, msg: str) -> bool:
    """
    对给定的字符串和签名字符串验签
    :param path: 公钥文件路径
    :param sign_str: 加签的字符串
    :param msg: 需要验签的字符串
    :return: True:验证成功,False:验证失败
    """
    with open(path, 'r', encoding='utf-8') as f:
        pub_pkcs = f.read()
    print('公钥:n' + pub_pkcs)
    pub_key = rsa.PublicKey.load_pkcs1(pub_pkcs.encode())
    result = rsa.verify(msg.encode(), b64decode(sign_str), pub_key)
    if result == 'SHA-1':
        return True
    else:
        return False


当对方(如java)来请求我们的python算法模型时,需要给定信号告诉对方,我的模型已经是否运行完毕,成功或失败及错误信息。

回调接口:


# 回调接口
try:
      模型效果 = 运行我的算法主函数

    # sign是使用rsa加密算法对jobExcuteInfo中的runId加签
    # modelOutput:模型输出数据,推荐模型中是AUC的值
    # jobExcuteInfo: 新的入参中包含有,直接取值
    # completed: 模型是否执行成功,如果中途失败,值为false,在失败的地方直接调用这个接口;
    #            否则值为true,在程序全部执行完成后再调用此接口
    # sign: 加签信息,对jobExcuteInfo中的runId进行加签,根据私钥,使用rsa加签
    param = {'modelOutput': 模型效果, 'jobExcuteInfo': 参数字典['jobExcuteInfo'],
          'complete': True, 'errorMsg': '', 'sign': sign(absolute_path+'/config/rsa.pri.pkcs1.pem', 要加签的信息)}
except Exception as e:
    param = {'modelOutput': 0.0, 'jobExcuteInfo': 参数字典['jobExcuteInfo'],
              'complete': False, 'errorMsg': traceback.format_exc(), 'sign': sign(absolute_path+'/config/rsa.pri.pkcs1.pem', 要加签的信息)}
finally:
    # 回调接口
    call_back_url = 'http://对方给你的网址'
    requests.post(call_back_url, json.dumps(param))


=============以上就是 回调接口+rsa私钥加签 的过程啦=========

以下是原理科普,可以参考以下教程:

RSA算法原理(一) - 阮一峰的网络日志

python RSA 密钥对的获取 数据加解密 加签验签

python RSA加密、解密、签名


对称加密:
描述: 加密解密使用同样的密钥。
特点: 速度快,安全性一般。
举例:DES、3DES、AES
使用场景:对大量数据进行加解密。


非对称加密:
描述:加解密使用不同的密钥。
特点:速度慢,安全性较高。
举例:RSA
使用场景:在对称加密前,使用非对称加密传输公共的密钥。


不可逆加密:
描述:只能加密,不能解密,加密过程不可逆。
特点:不可逆加密。
举例:md5
使用场景:使用md5(md5(password)),使用双重不可逆加密对用户密码加密,并存入数据库。在验证用户密码的时候,将待验证的数据进行双重加密后与数据库中的数据作比较即可。