Python Flask+Pandas+Plotly实战(一)
我不是一个伟大的程序员,我只是一个具有良好习惯的优秀程序员。― Kent Beck
Flask简介
Flask是一个Python的一个 Web 框架,负责管理应用所需的所有路由,这样你就不用自己编写相关代码了!
在浏览器中输入 “http://www.baidu.com” – 你的计算机就会向存储百度网站的另一台机器(比如服务器 server)发送一个请求,然后百度服务器会向你发送浏览器渲染网站所需要的文件。百度的计算机被称为服务器,因为它在你发出请求后,向你提供了发送文件的“服务”。
Web 地址的 HTTP 是 Hypter-Text Transfer Protocol 的缩写,意为超文本传输协议。HTTP 定义了通过互联网发送和接收消息的标准方式。
当你在浏览器中按下回车键时,你的计算机就在传达这样的信息“请给我 www.baidu.com 网页的所有文件”。这条信息使用 HTTP 管理的语法发送到服务器,然后服务器也通过协议将文件发送回来。
服务器上需要有一些软件可以解释这些 HTTP 请求并发送正确的文件,这就是像 Flask 这样的 Web 框架发挥作用的地方。框架会将代码抽象,完成接收请求、解释请求并发送正确的文件。
为什么选择Flask?
- 首先,最重要的原因是 Flask 是用 Python 编写的,对于只会Python的来说不需要另外学习一门语言。
- Flask 也是一个相对简单的框架,因此适合制作小型的 Web 应用。
- 因为 Flask 是用 Python 编写的,所以你可以将 Flask 与任何其他的 Python 库一起使用,包括 pandas、numpy 和 scikit-learn。在本项目中,将使用pandas库对数据进行预处理。
安装Flask
可直接使用pip和conda两种方式安装Flask包
pip install flask
conda install flask
最简单的Flask实例
首先我们将使用Flask实现一个最简单的网页App,创建一个名为routes.py文件,写入如下代码
import flask from Flask #从flask库中导入Flask类
app = Flask(__name__) #定义app实例
@app.route('/') #使用app.route装饰器
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run(host='0.0.0.0',port=5000) #启动服务
app
是Flask的实例,它接收包或者模块的名字作为参数,但一般都是传递__name__
让flask.helpers.get_root_path
函数通过传入这个名字确定程序的根目录,以便获得静态文件和模板文件的目录
使用app.route
装饰器会将URL和执行的视图函数的关系保存到app.url_map
属性上,处理URL和视图函数的关系的程序就是路由,这里的视图函数就是hello,那么什么是装饰器呢?app.route的作用是什么呢
以下简要论述Python中装饰器的作用1:
def decorator_factory(enter_message, exit_message):
def simple_decorator(f):
def wrapper():
print(enter_message)
f()
print(exit_message)
return wrapper
return simple_decorator
def goal():
print('I need to be executed!')
- 外层
decorator factory
函数传入两个字符串,没有返回值 - 内层
simple decorator
函数传入一个函数,并返回自身 - 最内层
wrapper
函数没有传入值,将分别执行两个print函数以及上一层函数传入的f,并且返回自身
在不使用装饰器之前,若要得到打印值
outer = decorator_factory('start','end')
outer
<function __main__.decorator_factory.<locals>.simple_decorator(f)>
因为执行decorator_factory得到的是simple_decorator,故需要继续传入函数
inner = outer(goal)
inner
<function __main__.decorator_factory.<locals>.simple_decorator.<locals>.wrapper()>
发现得到的inner
依旧是函数,所以需要执行此函数才能得到最终的结果
inner()
start
I need to be executed!
end
由此才得到了最终的结果,而如果使用装饰器@
,则可以省去这些繁琐的步骤
@decorator_factory('start','end')
def func():
print('I need to be executed!')
func()
start
I need to be executed!
end
以下简要论述app.route的作用:
在了解了装饰器的基本作用后,让我们将目光回到之前创建的app实例,它具体的作用是什么?为了理解它的基本作用,我们先创建一个自己的类,NotFlask
class NotFlask():
def route(self, route_str):
def decorator(f):
return f
return decorator
app = NotFlask()
@app.route("/")
def hello():
return "Hello World!"
可能会发现,这个装饰器和上一个定义的装饰器的主要区别在于,这个装饰器本身没有任何作用,只是为了让我们可以访问这个函数,事实上,当我们执行hello
函数,将直接返回hello
函数的内容
hello()
Hello World!
所以,我们接下去要做的是利用decorator
函数,存储我们的路由地址,为了实现这一目的,我们将定义一个字典,用来储存地址信息
class NotFlask():
def __init__(self):
self.routes = {}
def route(self, route_str):
def decorator(f):
self.routes[route_str] = f
return f
return decorator
app = NotFlask()
@app.route("/")
def hello():
return "Hello World!"
当我们每次访问route
函数时,routes
字典会添加路由地址,并将传入的f函数存到对应的字典值中,所以,当我们想访问routes
中的地址时,得到的就是传入函数
app.routes['/']()
Hello World!
我们已实现了通过访问decorator
函数存储路由地址的目的,但是,如果没有办法访问字典中路由地址对应的传入函数该怎么办?为此,我们在NotFlask
类中添加一个server
函数,来检查传入函数是否可以访问
class NotFlask():
def __init__(self):
self.routes = {}
def route(self, route_str):
def decorator(f):
self.routes[route_str] = f
return f
return decorator
def serve(self, path):
view_function = self.routes.get(path) #查字典
if view_function:
return view_function()
else:
raise ValueError('Route "{}"" has not been registered'.format(path))
app = NotFlask()
@app.route("/")
def hello():
return "Hello World!"
print(app.serve('/'))
Hello World!
在简要解释了app.route的作用后,让我们再看一看flask库中route的具体decorator,其中rule
是路由地址,比如"/"
,通过add_url_rule
函数添加到url_map
中
def decorator(f):
endpoint = options.pop("endpoint", None)
self.add_url_rule(rule, endpoint, f, **options)
return f
最后执行app.run
就可以启动服务了。默认Flask只监听虚拟机的本地127.0.0.1这个地址,端口为5000,0.0.0.0表示监听所有地址,这样就可以在本机访问了。当我们访问“http://127.0.0.1:5000/”,通过app.url_map
找到注册的“/”这个URL模式,就找到了对应的hello_world函数执行,返回“hello world!”,状态码为200。如果访问一个不存在的路径,如访问“http://127.0.0.1:5000/a”,Flask找不到对应的模式,就会向浏览器返回“Not Found”,状态码为404
Flask 访问HTML文件
在上一个实例中,我们实现了在网页中成功显示”Hello Wordl !”,但实际上,要做出一个完整的网页App,我们还需要掌握前端知识如html、css以及javascript等。接下去我们将创建不同的路由地址,并且访问对应的html文件
我们将创建一些需要的文件夹以及文件,新建WebApp并在其中创建如下文件/文件夹
execute.py
文件是最终执行的文件,demo
文件夹中创建templates
文件夹、__init__.py
文件和routes.py
,routes.py
是创建路由地址并访问html文件的程序,在templates
文件夹中创建homepage.html
, subpage1.html
和subpage2.html
网页文件
首先我们将在__init__.py
写入代码,当访问demo文件夹时,会自动先执行__init__.py
中的内容,我们在__init__.py
文件中
- 从flask库导入Flask类
- 定义Flask实例app
- 导入routes库
from flask import Flask
app = Flask(__name__)
from demo import routes
其次我们来看看routes.py
文件中该实现什么功能,我们从flask库中导入了render_template函数,flask框架通过render_template函数实现模版的渲染,可以简单将此函数的功能视为找到html文件并成功显示在页面中,需要注意的是,render_template函数会默认寻找templates
文件夹中的html文件,故文件夹名必须为templates
并与routes.py
文件在同一路径下。此文件定义了三个路由地址,分别对应三个不同的html文件(路由地址名无需与文件名相同,此处是为了方便)
from demo import app #将首先执行__init__.py中app=Flask(__name__)
from flask import render_template
@app.route('/')
def homepage():
return render_template('homepage.html')
@app.route('/subpage1')
def subpage1():
return render_template('subpage1.html')
@app.route('/subpage2')
def subpage2():
return render_template('subpage2.html')
homepage.html
, subpage1.html
, subpage2.html
中的模版如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>homepage</title>
</head>
<body>
This is homepage
</body>
</html>
最后,让我们回到WebApp中的execute.py
文件,执行app.run函数
from demo import app
app.run(host='0.0.0.0', port=5000, debug=True)
在终端执行python execute.py
命令并可成功访问本地地址
- 0.0.0.0:5000/ 返回:This is homepage
- 0.0.0.0:5000/subpage1 返回:This is subpage1
- 0.0.0.0:5000/subpage2 返回:This is subpage2
总结
在此篇文章中,我们介绍了什么是Flask,为什么要用Flask框架,并且实现了一个最简单的网页app和创建不同路由地址访问相应的html文件。
在Python Flask+Pandas+Plotly实战(二)中,将使用World Bank的数据通过pandas库进行数据清洗之后,显示在网页中