【星海出品】flask (四) 三方工具使用

  1. 学习的灵魂是公社,学习的目标是人民自治.
  2. 学习是非暴力革命方式的社会改革.
  3. 学习是人民对抗资本剥夺的文明方式.
  4. 学习失败了,就如同巴黎公社失败了一样.但是它为今后进行成功的社会改革指明了正确的方向.
  5. 学习的逻辑并不复杂,一句话,必须让知识数量与知识价值基本吻合.
  6. 管理学习也不复杂,就是要让学习的量稳定的波动于最小正值区间内.
  7. 当然,这在管理上是非常苦难的.
  8. 第一,我们必须有大量的前期积累.比如知识储备,知识变现能力,知识获取途径等等.
  9. 第二,我们必须严格控制知识的滥用.知识的滥教,确保知识的数量不背离知识的价值.
  10. 第三.我们必须建立强大的均输平准手段,以应对来自外部不确定的冲击.
  11. 总之,要站稳立场,要确立人民主体性,就一定可以管理好知识.
  12. 最后再一次向陈云等老一辈的无产阶级革命家表示敬意.
在开发时,每次更改 Flask 项目代码后,都需要手动重启 Flask 服务器。为了提高开发效率,可以使用 Flask 的自动重载功能,使 Flask 服务器能够自动检测到代码更改并自动重启。

具体实现方法如下:

在 Flask 项目的入口文件中,导入 werkzeug.serving 模块中的 run_simple 函数

Werkzeug 是一个 Python 的 WSGI 工具库,它可以用来构建 Web 应用程序。

python 复制代码
from werkzeug.serving import run_simple

使用 run_simple 函数启动 Flask 服务器,并设置 use_reloader=True 表示启用自动重载:

python 复制代码
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello, World!'

if __name__ == '__main__':
    app.run(debug=True, use_reloader=True)
python 复制代码
from werkzeug.wrappers import Request, Response
 
@Request.application
def application(request):
    return Response('Hello world')
 
if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 5000, application)

使用 @Request.application 装饰器将 application 函数转换为一个 WSGI 应用程序。然后使用

run_simple 函数在本地的 5000 端口运行应用程序。

python 复制代码
def run_simple(hostname, port, application, use_reloader=False,
               use_debugger=False, use_evalex=True,
               extra_files=None, reloader_interval=1, threaded=False,
               processes=1, request_handler=None, static_files=None,
               passthrough_errors=False, ssl_context=None):
    # 这方法还是比较短的,但是注释写得很详细,由于篇幅问题,就把源码中的注释省略了
    if use_debugger:
        from werkzeug.debug import DebuggedApplication
        application = DebuggedApplication(application, use_evalex)
    if static_files:
        from werkzeug.wsgi import SharedDataMiddleware
        application = SharedDataMiddleware(application, static_files)

    def inner():
        make_server(hostname, port, application, threaded,
                    processes, request_handler,
                    passthrough_errors, ssl_context).serve_forever()

    if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
        display_hostname = hostname != '*' and hostname or 'localhost'
        if ':' in display_hostname:
            display_hostname = '[%s]' % display_hostname
        _log('info', ' * Running on %s://%s:%d/', ssl_context is None
             and 'http' or 'https', display_hostname, port)
    if use_reloader:
        # Create and destroy a socket so that any exceptions are raised before
        # we spawn a separate Python interpreter and lose this ability.
        test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        test_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        test_socket.bind((hostname, port))
        test_socket.close()
        run_with_reloader(inner, extra_files, reloader_interval)
    else:
        inner()

模板渲染

虽然 jinja2 是一个单独的库,但是由于 flask 依赖了jinja2,所以不必单独安装。

python 复制代码
 from flask import render_template

使用

python 复制代码
 @app.route('/template')
 def template():  # put application's code here
     // 渲染
     return render_template('demo.html')

动态渲染

还是使用 jinja2 的 render_template

通过blog_id 与 HTML中 {{ blog_id }} 关联

python 复制代码
 @app.route('/template/blog/<blog_id>')
 def template(blog_id):  # put application's code here
     return render_template('demo.html', blog_id=blog_id)
html 复制代码
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8" />
     <title>Title</title>
   </head>
   <body>
     <a href="www.baidu.com">百度</a>
     <div class="header">这里是博客{{ blog_id }}</div>
   </body>
 </html>

支持其他类型的传参

python 复制代码
 @app.route('/template/blog/<blog_id>')
 def template(blog_id):  # put application's code here
     uesr = User('lijiajun', 'wy15195382735@163.com')
     person = {
         'username': 'zhangsan',
         'email': 'zhangsan的email'
     }
     return render_template('demo.html', blog_id=blog_id, user=uesr, person=person)

demo.html

html 复制代码
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8" />
     <title>Title</title>
   </head>
   <body>
     <a href="www.baidu.com">百度</a>
     <div class="header">这里是博客{{ blog_id }}</div>
     <div>{{ user }}</div>
     <div>{{ user.username }}</div>
     <div>{{ user.email }}</div>
     <div>{{ person.username }}</div>
     <div>{{ user.email }}</div>
   </body>
 </html>

使用过滤器

使用管道符号 | 即可。 <div>{``{ user.email | length }}</div>

自定义过滤器

python 复制代码
 def filter(value):
     return value.upper()
 ​
 ​
 # 增加过滤器
 app.add_template_filter(filter, 'filter')
 <div>{{ user.email | filter }}</div>

jinja2的语句

html 复制代码
<div>
    {% if age > 18 %}可以进入 {% endif %} {% if age < 18 %} 禁止进入{% endif %}
</div>
html 复制代码
<div>
    {% for foo in age %}​
    {% endfor %}​
</div>

组件传参

demo.html

html 复制代码
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8" />
     <title>test</title>
   </head>
   <body>
     <div>
       {% extends 'component.html' %} {% block content %} 我是传过来的内容 {%
       endblock %} {% block title %} 我是传过来的标题 {% endblock %}
     </div>
   </body>
 </html>

component.html

html 复制代码
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8" />
     <title>这是一个组件</title>
   </head>
   <body>
     这是一个组件 {% block title %}{% endblock %} {% block content %}{% endblock
     %}
   </body>
 </html>

加载图片

html 复制代码
 <body>
     <div>
         <img src='{{ url_for("static",filename="image.png") }}' alt="" />
     </div>
 </body>

加载Css文件

html 复制代码
 <head>
     <meta charset="UTF-8" />
     <title>test</title>
     <link rel="stylesheet" href='{{ url_for("static",filename="demo.css") }}' />
 </head>

加载Js文件

html 复制代码
 <script src='{{ url_for("static",filename="demo.js")}}'></script>

flask 连接 数据库

bash 复制代码
 pip install pymysql

我们不会直接使用这个包去操作数据库,因为需要写原生的SQL语句,我们最好使用 orm。

所以我们还需要下一个:

bash 复制代码
 pip install flask-sqlalchemy

sqlalchemy 给我们提供了 orm 的技术,可以让我们像操作普通对象一样去操作数据库。

这个需要额外安装,因为 flask 没有这个依赖。

python 复制代码
from flask_sqlalchemy import SQLAlchemy

创建SQLAlchemy实例对象,命名为db,将flask的实例对象app作为参数传给SQLAlchemy,将db和app联系起来,可以调用其相关功能

bash 复制代码
db = SQLAlchemy(app)

使用gunicorn启动flask

python 复制代码
gunicorn app:app -c gunicorn.conf.py > gun.log 2>&1 &

一 Gunicorn是基于unix系统,被广泛应用的高性能的Python WSGI HTTP Server。用来解析HTTP请求的网关服务。

它通常是在进行反向代理(如nginx),或者进行负载均衡(如 AWS ELB)和一个web 应用(比如 Django 或者 Flask)之间。

它的运行模型基于pre-fork worker 模型,即就是支持eventlet,也支持greenlet。

二、gunicorn特点

其特点:1、能和大多数的Python Web框架兼容;

2、简单易上手;

3、轻量级的资源消耗;

4、目前,gunicorn只能运行在Linux环境中,不支持windows平台

bash 复制代码
gunicorn -w 5 -b 0.0.0.0:6000 main:app

解释下参数含义:

-w :表示工作进程数

-b :访问地址和端口

main :flask启动python文件名

app :脚本中创建的Flask对象名

python 复制代码
from flask import Flask

app = Flask(__name__)


@app.route('/',methods=['GET'])
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=6000)

也可以根据文件启动

bash 复制代码
gunicorn -c config.py main:app
bash 复制代码
cat config.py
# 是否开启debug模式
debug = True
# 访问地址
bind = "0.0.0.0:6000"
# 工作进程数
workers = 2
# 工作线程数
threads = 2
# 超时时间
timeout = 600
# 输出日志级别
loglevel = 'debug'
# 存放日志路径
pidfile = "log/gunicorn.pid"
# 存放日志路径
accesslog = "log/access.log"
# 存放日志路径
errorlog = "log/debug.log"
# gunicorn + apscheduler场景下,解决多worker运行定时任务重复执行的问题
preload_app = True
bash 复制代码
-c CONFIG    : CONFIG,配置文件的路径,通过配置文件启动;生产环境使用;

-b ADDRESS   : ADDRESS,ip加端口,绑定运行的主机;

-w INT, --workers INT:用于处理工作进程的数量,为正整数,默认为1;

-k STRTING, --worker-class STRTING:要使用的工作模式,默认为sync异步,可以下载eventlet和gevent并指定

--threads INT:处理请求的工作线程数,使用指定数量的线程运行每个worker。为正整数,默认为1。

--worker-connections INT:最大客户端并发数量,默认情况下这个值为1000。

--backlog int:未决连接的最大数量,即等待服务的客户的数量。默认2048个,一般不修改;

-p FILE, --pid FILE:设置pid文件的文件名,如果不设置将不会创建pid文件


--access-logfile FILE   :  要写入的访问日志目录

--access-logformat STRING:要写入的访问日志格式

--error-logfile FILE, --log-file FILE  :  要写入错误日志的文件目录。

--log-level LEVEL   :   错误日志输出等级。


--limit-request-line INT   :  HTTP请求头的行数的最大大小,此参数用于限制HTTP请求行的允许大小,默认情况下,这个值为4094。值是0~8190的数字。

--limit-request-fields INT   :  限制HTTP请求中请求头字段的数量。此字段用于限制请求头字段的数量以防止DDOS攻击,默认情况下,这个值为100,这个值不能超过32768

--limit-request-field-size INT  :  限制HTTP请求中请求头的大小,默认情况下这个值为8190字节。值是一个整数或者0,当该值为0时,表示将对请求头大小不做限制


-t INT, --timeout INT:超过这么多秒后工作将被杀掉,并重新启动。一般设定为30秒;

--daemon: 是否以守护进程启动,默认false;

--chdir: 在加载应用程序之前切换目录;

--graceful-timeout INT:默认情况下,这个值为30,在超时(从接收到重启信号开始)之后仍然活着的工作将被强行杀死;一般使用默认;

--keep-alive INT:在keep-alive连接上等待请求的秒数,默认情况下值为2。一般设定在1~5秒之间。

--reload:默认为False。此设置用于开发,每当应用程序发生更改时,都会导致工作重新启动。

--spew:打印服务器执行过的每一条语句,默认False。此选择为原子性的,即要么全部打印,要么全部不打印;

--check-config   :显示现在的配置,默认值为False,即显示。

-e ENV, --env ENV: 设置环境变量;
相关推荐
零意@7 分钟前
ubuntu切换不同版本的python
windows·python·ubuntu
思忖小下18 分钟前
Python基础学习_01
python
q567315231 小时前
在 Bash 中获取 Python 模块变量列
开发语言·python·bash
是萝卜干呀1 小时前
Backend - Python 爬取网页数据并保存在Excel文件中
python·excel·table·xlwt·爬取网页数据
代码欢乐豆1 小时前
数据采集之selenium模拟登录
python·selenium·测试工具
许野平1 小时前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
狂奔solar1 小时前
yelp数据集上识别潜在的热门商家
开发语言·python
Tassel_YUE1 小时前
网络自动化04:python实现ACL匹配信息(主机与主机信息)
网络·python·自动化
聪明的墨菲特i2 小时前
Python爬虫学习
爬虫·python·学习
努力的家伙是不讨厌的3 小时前
解析json导出csv或者直接入库
开发语言·python·json