赞
踩
昨天完用flask成功部署了pytorch模型,成功完成了一个自己的项目,这是我个人生涯的一大步。按照惯例,写下这个备忘贴,主要是为了方便自己回忆的,大家能学到什么各凭本事。
深度学习五花八门,直接用flask部署深度学习pytorch模型,不利于入门,因此我推荐先部署一个极其简单的机器学习模型试试手。第一节会教你:我应该这么做,思路是什么。
web截图:
参考链接:
参考代码:
GitHub - YuGong123/Flask_house_price_predict
目录结构:
web界面,page.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <div align="center">
- <h2>使用Flask部署机器学习模型Demo——房价预测</h2>
- <br>
- <form action="{{ url_for('predict')}}" method="post">
- <b>房子英尺数</b><input type="text" name="housesize" required />
- <br>
- <button type="submit">预测房价</button>
- </form>
- <br>
- {{ prediction_display_area }}
- </div>
-
- </body>
- </html>
服务器程序——载入模型,命名app.py
- import numpy as np
- from flask import Flask, request, jsonify, render_template
- import pickle
-
- app = Flask(__name__)
- model = pickle.load(open('model.pkl','rb'))
-
- @app.route('/')
- def home():
- return render_template('page.html')
-
- @app.route('/predict', methods=['POST'])
- def predict():
- features_list = [float(x) for x in request.form.values()]
- features = np.array(features_list).reshape(1,-1)
- predict_outcome_list = model.predict(features)
- predict_outcome = round(predict_outcome_list[0],2)
-
- return render_template('page.html',prediction_display_area='预测价格为:{}'.format(predict_outcome))
-
- if __name__ == "__main__":
- app.run(port=80,debug = True)
使用Flask远程上传图片到服务器,并把获取到的图片显示到前端页面上。这个也是我项目代码的模板,简单实用,十分重要。
目录结构:
upload_pictures.py 代码:
1)该接口采用 POST 方法,需要登录;
2)接着,检查请求中是否有 'file' 关键词,然后取出文件,判断文件是否为空或是否合法;
- # coding:utf-8
-
- from flask import Flask, render_template, request, redirect, url_for, make_response,jsonify
- from werkzeug.utils import secure_filename
- import os
- import cv2
- import time
-
- from datetime import timedelta
-
- #设置允许的文件格式
- ALLOWED_EXTENSIONS = set(['png', 'jpg', 'JPG', 'PNG', 'bmp'])
-
- def allowed_file(filename):
- return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
-
- app = Flask(__name__)
- # 设置静态文件缓存过期时间
- app.send_file_max_age_default = timedelta(seconds=1)
-
-
- # @app.route('/upload', methods=['POST', 'GET'])
- @app.route('/upload', methods=['POST', 'GET']) # 添加路由
- def upload():
- if request.method == 'POST':
- f = request.files['file']
-
- if not (f and allowed_file(f.filename)):
- return jsonify({"error": 1001, "msg": "请检查上传的图片类型,仅限于png、PNG、jpg、JPG、bmp"})
-
- user_input = request.form.get("name")
-
- basepath = os.path.dirname(__file__) # 当前文件所在路径
-
- upload_path = os.path.join(basepath, 'static/images', secure_filename(f.filename)) # 注意:没有的文件夹一定要先创建,不然会提示没有该路径
- # upload_path = os.path.join(basepath, 'static/images','test.jpg') #注意:没有的文件夹一定要先创建,不然会提示没有该路径
- f.save(upload_path)
-
- # 使用Opencv转换一下图片格式和名称
- img = cv2.imread(upload_path)
- cv2.imwrite(os.path.join(basepath, 'static/images', 'test.jpg'), img)
-
- return render_template('upload_ok.html',userinput=user_input,val1=time.time())
-
- return render_template('upload.html')
-
-
- if __name__ == '__main__':
- # app.debug = True
- app.run(host='0.0.0.0', port=8987, debug=True)
upload_ok.html 文件代码:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Flask上传图片演示</title>
- </head>
- <body>
- <h1>使用Flask上传本地图片并显示示例一</h1>
- <form action="" enctype='multipart/form-data' method='POST'>
- <input type="file" name="file" style="margin-top:20px;"/>
- <br>
- <i>请输入你当前的心情(开心、超开心、超超开心):</i>
- <input type="text" class="txt_input" name="name" value="超超开心" style="margin-top:10px;"/>
- <input type="submit" value="上传" class="button-new" style="margin-top:15px;"/>
- </form>
- <h1>阁下的心情是:{{userinput}}!</h1>
- <img src="{{ url_for('static', filename= './images/test.jpg',_t=val1) }}" width="400" height="400" alt="你的图片被外星人劫持了~~"/>
- </body>
- </html>
值得注意的一点是:这篇代码没有直接对用户上传的图片进行处理,而是先将他们放到'static/images' 文件夹下保存,这样十分方便我们用path路径等方法进行后续处理。而且,路径是写死的,这样更方便。
web网页截图:
参考文章:
参考代码:
https://github.com/YuGong123/Flask_upload_pictures
十分重要的2个参考链接:
[python][flask] Flask 图片上传与下载例子(支持漂亮的拖拽上传)
这篇用了一种巧妙的方法,实现了将python后台制作的图片,放到html等前端显示。原理:Python在后台把图片处理为Base64位的格式,再把Base64格式的图片在html用img控件显示。
Python代码:
- from flask import Flask, jsonify, request, render_template
- from flask_cors import CORS
-
- app = Flask(__name__) # 实例化,可视为固定格式
- app.debug = True # Flask内置了调试模式,可以自动重载代码并显示调试信息
- app.config['JSON_AS_ASCII'] = False # 解决flask接口中文数据编码问题
-
- #设置可跨域范围
- CORS(app, supports_credentials=True)
-
- # 展示Flask如何读取服务器本地图片, 并返回图片流给前端显示的例子
- def return_img_stream(img_local_path):
- """
- 工具函数:
- 获取本地图片流
- :param img_local_path:文件单张图片的本地绝对路径
- :return: 图片流
- """
- import base64
- img_stream = ''
- with open(img_local_path, 'rb') as img_f:
- img_stream = img_f.read()
- img_stream = base64.b64encode(img_stream).decode()
- return img_stream
-
- // 跳转到html页面显示图片 app.route()为跳转路由,类似springboot
- @app.route('/index')
- def hello_world():
- img_path = 'static/img/demo.png'
- img_stream = return_img_stream(img_path)
- # render_template()函数是flask函数,它从模版文件夹templates中呈现给定的模板上下文。
- return render_template('index.html',img_stream=img_stream)
-
- // 主函数
- if __name__ == '__main__':
- # app.run(host, port, debug, options)
- # 默认值:host="127.0.0.1", port=5000, debug=False
- app.run(host="127.0.0.1", port=5010)
这里十分重要,因为采用static静态文件夹保存图片,我们可以轻易的捕捉到图片路径,再通过传参的方式:
return render_template('index.html', img_stream=img_stream)
将后台图片送到前端展示。
html代码:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <img src="data:;base64,{{ img_stream }}">
- </body>
- </html>
web网页图:
参考代码:
GitHub - YuGong123/Flask_show_images_on_web
图片下载比较简单,就是调用 send_from_directory
函数,就能够把 static 目录下的对应文件发出:(我们一般把各种用于外面访问的静态图片、JS、CSS 等放在 static 文件中)
写法一:用get方法,到指定目录,下载指定文件。
- #get方法:指定目录下载文件
- @server.route('/download', methods=['get'])#/download路由地址,methods请求方法
- def download():
- fpath = request.values.get('path', '') #获取文件路径
- fname = request.values.get('filename', '') #获取文件名
- if fname.strip() and fpath.strip():
- print(fname, fpath)
- if os.path.isfile(os.path.join(fpath,fname)) and os.path.isdir(fpath):
- return send_from_directory(fpath, fname, as_attachment=True) #返回要下载的文件内容给客户端
- else:
- return '{"msg":"参数不正确"}'
- else:
- return '{"msg":"请输入参数"}'
写法二:下载指定文件,使用默认路径,跳过了路径拼接。
- @bp.route('/download/<name>')
- def download_file(name):
- return send_from_directory(app.config["UPLOAD_FOLDER"], name) #返回要下载的文件内容给客户端
写法三:
这是我的写法,直接将路径在后台写死,用户无从选择,只能下载"static/images/test.jpg"。当用户点击“下载预测图”时,无需传参,点击下载就行。
<a href="http://localhost:5000/download">下载预测图</a>
- # 注意,下载路径 "download_path" 是写死的
- @app.route('/download/', methods=['GET'])
- def download():
- return send_from_directory('static/images', 'test.jpg', as_attachment=True)
可能有人会问,前面不是已经说过了如何展示图片了吗?为什么还要讲?
我可以告诉你,前面的方法,都是先将用户提供的图片备份到后台。之后,用户不点击提交按钮是看不到的,即不触发"post"请求是看不到图片的。
这里是告诉你如何用jqury库,来实现图片展示,即,在不点击提交按钮的情况下,如何实时展示图片。
核心代码:
- <!DOCTYPE html>
- <html>
- <head>
- <title>HTML5上传图片并预览</title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <script src="{{ url_for('static', filename='js/jquery.min.js') }}"></script>
- </head>
- <body>
- <!--<h3>请选择图片文件:PNG/JPG/JPEG/SVG/GIF</h3>-->
- <div style="text-align: left;margin-left:500px;margin-top:100px;" >
- <div style="float:left;">
- <a href="javascript:;" class="file">选择文件
- <input type="file" name="file" id="file0"><br>
- </a>
- <img src="" id="img0" style="margin-top:20px;width: 35rem;height: 30rem;">
- </div>
- <div style="float:left;margin-left:50px;">
- <input type="button" id="b0" onclick="test()" value="预测">
- <pre id="out" style="width:320px;height:50px;line-height: 50px;margin-top:20px;"></pre>
- </div>
- </div>
-
- <script type="text/javascript">
- $("#file0").change(function(){
- var objUrl = getObjectURL(this.files[0]) ;//获取文件信息
- console.log("objUrl = "+objUrl);
- if (objUrl) {
- $("#img0").attr("src", objUrl);
- }
- });
-
- function getObjectURL(file) {
- var url = null;
- if(window.createObjectURL!=undefined) {
- url = window.createObjectURL(file) ;
- }else if (window.URL!=undefined) { // mozilla(firefox)
- url = window.URL.createObjectURL(file) ;
- }else if (window.webkitURL!=undefined) { // webkit or chrome
- url = window.webkitURL.createObjectURL(file) ;
- }
- return url ;
- }
- </script>
- </body>
- </html>
-
-
核心思想:靠jquery提供的id选择器 "#file0" 找到input文本框,通过js找到图片框"#img0",给它添加src属性,并赋值。
参考代码:
https://github.com/YuGong123/pytorch_flask_service
完成了项目,想向小伙伴炫耀一下,但是只能本地访问,怎么让小伙伴用局域网访问?
有人说我们可以在程序中设置:
app.run(host='0.0.0.0',port=5000)
但这并无卵用, 解决方案:
然后设置参数:
这样就搞定了。
右键点击templates文件夹,之后如图所示:
参考链接:
打开pycharm-->文件-->设置-->插件,点击如图内容
点击加号,输入网址 https://plugins.zhile.io
回到插件主页,搜索eval reset
在pycharm主页面处,点击帮助,帮助栏下面会多出一个eval reset的选项。
点击后pycharm低端会出现选择栏目,这里不用在意内容,只需把Auto reset before per restart 打√,这样可以在每一次开启时自动重置试用时间,点击reset
参考链接:
pycharm专业版 没有试用30天按钮,需要登录的解决方案
这里个人推荐去官网下载pycharm-professional-2020.3.3.exe,可以避免无法使用选择 “30天试用” 的情况。
官网地址:
http://www.jetbrains.com/pycharm/download/#section=windows
有时候Pycharm的terminal中显示的是硬盘中的项目路径,但没有进入我们创建好的虚拟环境
这时候,我们需要在Pycharm>File>Tools>Terminal中切换powershell.exe为cmd.exe
本人在用pycharm内部的Git上传代码到Github上后,出现了已经一件令人十分悲伤的故事,PyCharm中的项目无法识别相对路径了。
问题出在PyCharm的Edit Configurations中:
解决方法:
参考链接:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。