作为一名统计学专业的学生,Python 对我而言,更多的是数据处理和统计分析工具。

但突然有一天,我有一个搞一个网站的想法,“拥有一个个人博客”应该是一件很酷的事情,既然想了那就得行动起来了。当然 Web 开发对我这种非科班学生来说基本就属于完全没有接触过,不过还好我会 Python。那就从 Python 入手,我很快就找到了 Flask,一个轻量的 Web 框架。当然我找资料的时候也找到了Django,但于我觉得对我而言“轻量”就够了,Django似乎看起来有些笨重(当然也可能是我的认知不足驾驭它)。

经过几天的折腾,我就初步搞定了博客的基础功能,也就是现在这样。样式啥的都从网上各种找找各种改改糊起来的,感谢互联网,看起来效果还行。

开发过程中,Flask 这样的 Web 框架解决和简化了很多问题,帮我避开了许多繁琐的底层细节。事实上我现在也不懂 HTTP 协议、TCP 协议,但我依然借助 Flask 搞出了这个博客,而且仅用了不到 200 行 Python 代码(当然前端页面代码这些还是挺多的,这里主要指后端)。

这篇文章我就想来讲讲,作为一个非专业开发, Web 框架帮助我解决了什么问题。

一、简化 HTTP 请求和响应的处理

我个人认为这是 Web 框架最核心的功能,试想一下。如果我什么都不用,单纯使用 Python 内置库从 TCP 请求开始讲数据包解析实现一个 HTTP 请求的解析再把回包封分拆写入 TCP的逻辑。这样一个过程,先不说我目前有没有这个能力,努力学学我想应该不是问题,但这就不是几天的事情了。 但用了 Web 框架就不一样了,所有的一切解析工作他都不帮你做了。Flask 这样的框架将这些底层细节封装起来,所有的信息都被包在了一个request对象里,我只需关注如何写我的页面逻辑即可。

二、简化路由分发逻辑

上文说到了解析 HTTP 请求的复杂性,实际上解析完还有一件事也很复杂,那就是路由。相较于数据分析中只关注数据读写和算法逻辑,Web 开发首先要解决“如何将用户的请求分发到正确的处理函数”。 如果是假设我的博客只有几个页面,可能一个 dict 或者几句 if-else 就可以完成简单的映射。但如果多了,这样就会显得很笨拙,如果还有参数,比如每个文章有自己的slug,那就更不一样了。最终会发现还是需要实现一个模式匹配机制来路由, Flask 的 @app.route 装饰器就可以快速实现这个事情

考虑下面的例子:

@app.route('/user/<username>', methods=['GET'])
def show_user_profile(username):
    # Flask 自动将 URL 中 <username> 部分提取出来作为参数
    return f"User: {username}"

Flask 会将这些路由规则转换为匹配模式,能够在请求到来时根据 Path 快速找到对应的函数。相比手动编写条件判断,这种方式明显更加清晰和高效。

三、错误捕捉处理

Web 服务有一个和数据处理不一样的地方就是持续服务。如果我写一个处理流,中间遇到了异常数据或者处理逻辑异常,Python会自动退出并打印出错误。这对 Web 服务可不行,试想如果一个处理函数报错了,Web 就报错退出,然后接下里所有用户都访问不了了,这明显不可理喻啊。所以我们在报错时至少需要保证服务的可持续,同时也要告诉用户我们有问题了,因为用户可看不见你的命令行报错日志。 统一的异常处理机制让我不必在每个函数中重复处理错误,同时也能确保最终用户获得统一而友好的错误提示。

四、认证和安全访问

对于新人来说,HTTP 本身还是有很多坑的。特别是安全相关的。想想如果我们自己来写一鉴权认证的逻辑,他肯定不如站在巨人的肩膀上,利用成熟的工具。

五、可插拔开发

Web 框架本身就是一个工具箱,你可以拿出其中一些工具来用,也可以自己写一些通用的功能。Flask 也可以很方便的把一些组件插入到请求的某个链路上,或者只针对某些满足要求的请求做一些统一的处理。

五、Web 框架未解决的问题

讲了 Flask 的各种好,但没有一样东西是万能的, Flask 或者说 Web 框架一样有它的能力边界。不是说他做不到,我更多的感觉是没有必要,less is more,有些问题明显需要其他层级的东西来解决而不是全部包裹在 Web 框架里。

  • 并发处理
    Flask 内置的开发服务器仅适用于学习和调试,性能并不好。我在实际使用中也经常出现突然因为某个请求一直处理完导致其他请求没有响应的情况。关于这块,我也正在学习,考虑借助 Gunicorn 或者其他组件来优化现在这种情况。

  • 多端口监听 我最近部署了博客之后,发现经常被插入恶意广告。查了一下,这是由于 HTTP 是纯文本协议,也就是说如果有中间人在服务器和你的用户之间监听,你们的通信是明文的,它可以对你们任何一方的内容插入任何信息。我遇到的广告也是这种情况。解决方案是部署使用 https,这样中间人如果有篡改行为接收方就可以知道。我们知道 http 的默认端口是 80,而https的默认端口是 443。而 Flask 自带的服务器并不能同时监听两个端口,一个处理 https 请求,另一个 处理 http 请求。这时需要借助nginx 或者其他专业的工具来处理(我还没研究透,所以这里就不先班门弄斧了)