Python 中的异常

在 Python 中,EAFP 的风格很受青睐,这种写法能让代码更加简洁,还可以避免一些重复判断和多线程竞争的问题。为此,了解并熟练使用异常是很重要的。 异常类 首先来看一下 Python 内置的异常类(有省略): BaseException +-- SystemExit +-- KeyboardInterrupt +-- GeneratorExit +-- Exception +-- StopIteration +-- StopAsyncIteration +-- ArithmeticError +-- AssertionError +-- AttributeError +-- BufferError +-- EOFError +-- ImportError +-- LookupError +-- MemoryError +-- NameError +-- OSError +-- ReferenceError +-- RuntimeError +-- SyntaxError +-- SystemError +-- TypeError +-- ValueError +-- Warning BaseException 是所有异常的老祖宗,但很少会用到,通常我们只需要 Exception,比如自定义一个错误类型: # 命名习惯一般以 Error 结尾 class CustomError(Exception): def __init__(self, message, status): # 这里最好把参数都放进去,之后会统一存在 e....

09-15 · 3 min

Python Import 源码阅读

浅析一下 Python 中的 Import 机制。代码版本:3.11.0 - 4dd8219。 Module & Package Import 的对象就是各种各样的模块,即 Module。如何定义呢?官方文档这样描述: A module is a file containing Python definitions and statements. 实际上,Module 可以是 Builtin,也可以是 C extension,但最常见的存在形式还是 *.py 文件。 一个 Module 同时也可能是 Package,此时它从文件升级为目录,就可以拥有 Submodule 了。Package 分为两种: Regular package:这类 Package 必须包含一个 __init__.py 文件,代表了这个 Module(Package) 本身。 Namespace package:如果不存在 __init__.py,Python 会将其创建为此类 Package。Namespace package 的特殊之处在于同名的 Package 可以出现在多个目录下,而 Import 完成之后又可以统一使用。 不管是哪一种 Package,都会有 __path__ 属性,指向目录的路径。属性值是个列表,这对于 Namespace package 尤为重要。除此之外,一个 Module 还有: __name__:模块名称。 __file__:文件位置。 __package__:主要是为了在 Relative import 时计算起点位置。 如果是 Package 则设置为 __name__。 如果非 Package 则设置为 Parent package 的名称(Top-level 的 Module 应为空字符串)。 如果以脚本执行,那么取值为 None。 How to Import 一般情况下 Import 都是通过 import 关键字完成的,可分为两大类:...

09-10 · 6 min

Sum of Total Strength of Wizards

前两天做了一道算法题,虽然没能成功解决,但是是一道很有意思的题目。 抛开题面的包装不谈,核心内容就是给定一个数组,计算它的所有子数组的最小值与加和的乘积的总和。 (这里要注意子数组的定义,一定是连续的,如果不连续的话叫做子序列。) 比如对于 [1, 2, 3] 来说,一共有六种情况: [1]: 1 * 1 = 1 [2]: 2 * 2 = 4 [3]: 3 * 3 = 9 [1, 2]: 1 * (1 + 2) = 3 [2, 3]: 2 * (2 + 3) = 10 [1, 2, 3]: 1 * (1 + 2 + 3) = 6 最后答案为 1 + 4 + 9 + 3 + 10 + 6 = 33。...

07-26 · 3 min

关于 CORS

说起 CORS,就不得不先提到 SOP(Same-origin policy):浏览器打开的网页只可以对该网页的同源网站发起请求。注意,受约束的主要是脚本代码,不包括图片或者 CSS 等资源(字体文件是个例外)。同源的定义包括三部分,即协议、域名和端口都要保持一致。 为了缓解 SOP 带来的严格限制,有几种主流的解决方案可以选择: CORS JSONP:利用 <script> 标签来请求非同源地址的 JSON 响应,同时配合一个预先定义的回调函数来处理响应数据。 WebSocket:WS 连接并不受同源策略的约束,但是在建立连接时服务端也需要判断 headers 中的 Origin 是否可以接受。 其中 CORS 应该是最实用的一种,相比 JSONP 只支持 GET 请求,前者扩展了各种 HTTP 方法的跨域调用。 CORS(Cross-origin resource sharing),是一种跨域共享资源的机制,它利用特定的 Headers 来保证跨域请求的安全性,这些请求分为两类:简单请求和非简单请求。 简单请求,包括 GET、HEAD 和 POST,这里 POST 的 Content-Type 仅限于下面三种: application/x-www-form-urlencoded multipart/form-data text/plain 对于这些请求来说,只需要保证 Access-Control-Allow-Origin 中匹配了当前网页的域名即可,如果是 * 的话表明所有的域名都是允许的。 非简单请求,比如 Content-Type 为 application/json 的 POST,会增加一次额外的 Preflight 请求,即先发送 OPTIONS 请求给服务器,然后通过响应中的一系列 Headers 决定是否可以进行真正的请求。这些 Headers 包括: Access-Control-Allow-Methods:服务器允许的跨域方法,比如 POST。 Access-Control-Allow-Headers:服务器允许的跨域头部,比如 Content-Type。 Access-Control-Max-Age:Preflight 请求结果的缓存时间,默认为 5s。 另外,如果想在 Chrome 中查看 Preflight 请求的话,打开 Network 标签,点击 Other filter 就可以看到了。...

05-17 · 1 min

Bottle 框架源码阅读

写这篇文章最开心的一点是终于可以用这张截图了: 相比名声在外的 Django/Flask/FastAPI,Bottle 可以说是非常不起眼了,甚至很多人并不知道它的存在。其实在很多方面,这个框架都极其优秀: 速度:截止到 2022-04-13,Bottle 在一众 Python Web 框架的测评中名列第二,要知道这可是十年以上的老前辈了。 易用性:Bottle 早在 Flask 之前就使用了装饰器来定义路由,此外还有全局可用的 Request/Response 对象。 文档:不仅将框架本身的使用讲得很清楚,还总结了很多 Web 场景下的解决方案。 代码质量:虽然为了 Python 2 做了不少兼容,但是代码很精炼,而且 Pythonic。 其他:Bottle 坚持单模块以及无第三方库依赖;仓库仍然在积极维护中。 换作几年前,我会一开始就使用并将 Bottle 研究透彻,而不是让自己淹没在 Django 浩瀚如烟的文档中。下面开始梳理 Bottle 源码的阅读理解。因为代码量不大,所以就直接看最新的版本了:0.11.1 - 5a6c620。 Web 框架的基本元素 参考 The Hitchhiker’s Guide to Python 的说法,一个 Web 框架要满足的基本功能: URL Routing Request and Response Objects Template Engine Development Web Server 从后端的角度来讲更重要的是 1、2、4 三项,其中 1 负责转发请求到对应的视图函数,2 是对 HTTP 协议元素的解析处理,而 4 决定了服务的部署方式和基础性能。 Bottle 在这几方面都做了很好的实现:路由上提供了通配符匹配和装饰器接口;请求和响应对象作为全局对象存在并保证了线程安全;Server 部署除了 Python 自带的 wsgiref 还支持绝大多数的 WSGI Server。...

04-22 · 6 min