一、概述
1. 需求的产生
电力系统方向的研究生在做项目的过程中,甲方常常需要将项目的代码部署到其自身的平台中,但是大部分甲方的平台都是基于java编写,python因其强大的科学计算能力而被实验室广泛使用,这就给程序的部署带来了困难。
通过和甲方的交流可以得知:他们可以通过http协议访问web应用从而实现对程序的远程调用。因此,可以将python程序封装成 Web 应用供用户远程访问并调用。
2. 工具准备
代码编辑器:VSCODE
本帖涉及的python程序均在VSCODE中编写和调试,因此需要先在vscode中部署python环境,具体详见在VScode中配置Python开发环境
Git
部署过程中需要将本地源代码推送到云服务器上,微软Azure支持本地Git部署,因此使用Git作为源代码上传工具,具体配置详见git的安装与配置教程-超详细版
微软Azure学生认证账号
Azure是微软旗下的云计算服务平台,提供服务器、云存储、AI等超过 200 种云服务,类似于国内的阿里云、腾讯云等(为什么不选国内的呢,主要是怕花钱开服务器却部署不成功,先拿免费的试试)。Azure学生订阅是Azure面向学生提供的一项免费订阅,包含多项免费的服务和100美元的免费额度。除了特定的免费服务外,使用其他服务产生的费用会在这100美元的额度中扣除。订阅的有效期是一年,如果一年后仍是学生身份则可以免费续订。具体申请过程详见学生福利白嫖之路——申请Azure学生订阅
3. 流程
Azure 提供了多种部署方式,但最简单的方式是使用 Azure App Service,它是一个完全托管的服务,支持快速部署 Python 应用。以下是一步一步如何将 Flask Web 应用部署到 Azure App Service 上的过程:
- 准备 Flask 应用
- 创建 Azure Web 应用(Azure App Service)
- 配置本地 Git 仓库部署
- 访问部署完成的应用
二、Python程序部署到Azure
一般甲方会提供项目的输入文件(如电网拓扑数据等,本文采用excel文件),通过调用你编写的python程序完成该项目核心算法的处理并获得一个输出文件(本文也采用excel文件),然后他们读取输出文件即可完成相应的展示。
1. 准备 Flask 应用
基于上述思路,首先需要在本地电脑上完成python程序的开发和调试,然后使用 Flask 框架将Python程序封装成 Web 应用,并确保该web应用可以在本地正确运行。
第一步:构建虚拟环境
建议为每一个项目单独设置虚拟环境,这样可以将每个项目使用的库隔离,以免库的版本冲突。接下来基于vscode构建虚拟环境。
在VSCode中打开项目文件夹,键盘输入快捷键“Shift+Ctrl+P”命令面板,输入“Python”,选择“Python:创建环境”。
选择创建“Venv”环境,可以选择第一节中安装的python 3.10.5来配置环境。当然,如果你安装了conda,也可以选择创建“Conda”环境,这样可以选择特定版本的python来配置环境。
等待右下角配置完成,直到左侧出现.venv文件夹,表示已完成配置。
接下来点击左下角的图标,如图红色框,然后选择终端,vscode会自动激活该虚拟环境(前提是当前位于项目文件夹)。
此时该虚拟环境内没有安装任何库,可以根据项目需要安装需要的库,这里以numpy为例:
可以看出,成功安装。
第二步:创建项目程序
在项目文件夹里创建文件夹example,添加项目python程序,这里以hazard.py作为示例,如前所述,该程序的功能是:读取输入文件
→
\rightarrow
→核心算法处理
→
\rightarrow
→输出结果文件。
hazard.py内容摘要如下:
import pandas as pd
import numpy as np
import math
import xarray as xr
from scipy.interpolate import CubicSpline
import os
def prob_cal (input_file):
#读取文件
base_dir = os.path.dirname(os.path.abspath(__file__)) # 当前脚本所在目录
file_path = os.path.join(base_dir, input_file) # 相对路径拼接
file1 = os.path.join(base_dir, 'static', 'era5_tcw.nc') #程序运行所需静态文件1
file2 = os.path.join(base_dir, 'static', 'era5_wind.nc') #程序运行所需静态文件2
ds_tcw = xr.open_dataset(file1)
ds_wind = xr.open_dataset(file2)
......#省略核心算法
#输出结果文件
output_file = os.path.join(base_dir,'output.xlsx')
with pd.ExcelWriter(output_file, engine="openpyxl") as writer:
out1.to_excel(writer, sheet_name="sheet1", index=False)
out2.to_excel(writer, sheet_name="sheet2", index=False)
return output_file
inputfile = "input.xlsx"
output = pro_cal(inputfile)
验证程序可以正确运行,接下来进入下一步。
第三步:创建Flask应用
首先pip安装flask库,然后修改上一步的代码以创建flask应用,该应用包括了文件上传、处理和下载功能,代码摘要如下:
import pandas as pd
import numpy as np
import math
import xarray as xr
from scipy.interpolate import CubicSpline
import os
def prob_cal (input_file):
......#省略代码
return output_file
# 创建 Flask 应用
app = Flask(__name__)
# 设置上传文件夹和允许的文件扩展名
app.config['UPLOAD_FOLDER'] = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'uploads')
app.config['ALLOWED_EXTENSIONS'] = {'xlsx'}
# 确保上传文件夹存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
@app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
# 检查请求中是否包含文件
if 'file' not in request.files:
return '没有文件部分', 400
file = request.files['file']
# 如果没有选择文件
if file.filename == '':
return '没有选择文件', 400
# 如果文件扩展名允许,保存文件
if file and allowed_file(file.filename):
filename = file.filename
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
# 调用处理函数
output_file = prob_cal(filepath)
# 返回处理后的文件作为下载文件
return send_file(output_file, as_attachment=True)
return render_template('upload.html')
# 启动 Flask Web 应用
if __name__ == '__main__':
port = int(os.environ.get('PORT', 5000)) # 使用环境变量配置端口
app.run(host='0.0.0.0', port=port)
第四步:创建 HTML 文件
在项目文件夹内创建templates 文件夹,并在templates 文件夹里面新建HTML文件upload.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>上传 Excel 文件</title>
</head>
<body>
<h1>上传您的 Excel 文件</h1>
<form method="POST" enctype="multipart/form-data">
<label for="file">选择一个 Excel 文件上传:</label>
<input type="file" name="file" id="file" required>
<button type="submit">上传并处理</button>
</form>
</body>
</html>
至此文件夹结构如图:
第五步:本地运行Flask应用
运行hazard.py,终端内出现如下界面
按住ctrl,点击图中网址,浏览器弹出如下网页
上传文件后,得到了目标输出文件,即表示本地运行成功。
第六步:创建 requirements.txt
在进行这一步之前,请先pip安装gunicorn库,免得推送部署时再向requirements.txt手动添加。
requirements.txt 文件用于列出所有的 Python 依赖。你可以通过在vscode终端输入以下命令自动生成:
pip freeze > requirements.txt
如图,
然后就可以在目录中看到生成的requirements.txt 文件了。即:
2. 创建 Azure Web 应用(Azure App Service)
进入Azure主页:https://portal.azure.com/#home,选择“创建资源”
然后创建web应用
然后新建资源组,我这里新建资源组命名为example1211;实例名称为hazard-example;选择发布“代码”,堆栈选择python 3.10;区域选择“East Asia”;定价计划选择“免费F1”(我这里选免费F1就够用了,实际根据自己需求选择)。
点击“查看+创建”。稍等片刻,继续点击左下角创建按钮。等待部署完成。
点击“转到资源”,再点击左侧导航栏的“部署中心”,“源”选择“本地Git”
会出现警告:
点击该红色警告,跳转到配置页面,将下图两个开关打开
点击“保存”,然后回到“部署中心”,然后再点击“保存”,得到下图界面
然后点击“本地Git/FTPS凭据”,得下图
3. 配置本地 Git 仓库部署
第一步:部署之前请将hazard.py最后的如下代码注释
因为我们要在云服务器上使用 Gunicorn 启动 Flask 应用,app.run() 会启动 Flask 内置的开发服务器,而 Gunicorn 是一个生产环境服务器,不需要 Flask 自带的开发服务器来运行应用。Gunicorn 会自动查找 Flask 应用的入口并启动它。
if __name__ == '__main__':
port = int(os.environ.get('PORT', 5000)) # 使用环境变量配置端口
app.run(host='0.0.0.0', port=port)
第二步:打开Git Bash桌面应用
如下图依次输入。
为了方便大家,上图输入的指令如下:
git init
git remote add azure *(刚才复制的链接)*
git add .
git commit -m "Deploy Flask app to Azure"
git push azure master
然后将触发 Azure 自动构建和部署过程。期间会弹出下图,输入刚才保存的用户名和密码即可。
等待数分钟,如下
第三步:azure内设置启动命令
点击azure“部署中心”下面的“配置”,找到“启动命令”一栏
输入下面代码,然后保存。
gunicorn -w 4 -b 0.0.0.0:$PORT hazard:app (这里只需要把hazard换成你自己推送的.py文件的名称即可)
顺带一提:
如果后续需要对已经推送的源文件进行任何修改,只需要在刚才的本地文件夹内修改即可,修改完保存,在vscode左侧导航栏的“源代码管理”便可以发现数字提示,提示你做了几处更改,点击去,悬停在更改的文件上,出现加好,点击加号暂存更改,再点击提交。
然后会弹出下图,在红色语句处我写的是delete apprun,其实是我刚才忘记注释本节开头的那段代码了。输入完成保存,然后关掉该文件即可
注意看左侧下方窗口,如下图
在这里可以看到,之前在git bash里的部署也出现在这里。
稍等片刻便可完成云服务器同步。
4. 访问部署完成的web应用
回到打开的AZURE网页,点击刚才部署的项目“概述”
如下图所示,红框内即为该应用的网址。点击该链接即可访问(访问之前最好重启一下应用)。可以看到顺利打开了应用,如下