流畅的 Python 读书笔记(二)

继续啃这本略微有些旧的书,《Fluent Python》第二版出版在即,预计今年四月份,它将会讲解到更新版本 Python 的特性,书中有提到 Python 3.10。第一版读下来也不会是浪费时间的。

还是数据结构,现在来到字典,dict 是 Python 语言的基石,在它内部也被广泛应用,比如 type(globals()) 是个  dict, globals() 的内容有我们能调用的全局函数。如果在编程中不想创建新对象的话,dict 几乎能表述需要的数据结构。

dict 就是一个 hash 表,它是 collections.abc 下 Mapping 和 MutableMapping 的子类。和其他语言中的字典一样,dict 的 key 必须实现了 __hash__()__qe__() 方法,否则不能作为 key,比如 list 是不能作 key 的。两个key 的 hash() 相等的话,那么  key1 == key2, 反之不一定。所以当 __eq__ 依赖于可变状态就不要去实现 __hash__ 方法. 阅读全文 >>

配置 AWS Lambda Python Logging

通常在 Python 应用中简单的配置使用内置的 logging 是这样的

假如文件名为 test.py, 用 python test.py 执行后输出

2022-01-25 21:02:47,231 - INFO - test(<module>:6) - hello world

在 Lambda 中的现象

可是这同样的代码放到 AWS Lambda Python 代码中却不灵验了,logging.info() 将得不到任何输出。 阅读全文 >>

流畅的 Python 读书笔记(一)

用了一段时间的 Python, 觉得还是有必要读一下《流畅的Python》这本书,它虽然是基于 Python 3.4 的,但 Python 自身的很多特性希望了解的更多,更深,或巩固,或扫扫死角。

对于少量属性的对象可以用 collections.namedtuple 快速构建一个类  Card = collections.namedtuple('Card', ['rank', 'suit']), 用 type(Card) 看到的就是一个  class, 第一个参数 Card 是类名,第二个参数列表里是属性名,然后用 card = Card('7', 'diamonds') 创建一个实例。PyCharm 也能正确识别出 Card 构建与使用对象时的属性 rank 和 suit.

现代从 Python 3.7 开始引入了 @dataclasses.dataclass 比 namedtuple 要方便些

@dataclasses.dataclass
class Card:
    rank: str
    suit: str = None

card = Card(rank='7', suit='diamonds')

或者用 pydantic 的 BaseModel 都比先前的 namedtuple 好用 阅读全文 >>

Celery(分布式任务队列)入门学习笔记

在步入到 AWS 后,设计一个典型的分布式计算任务模式是

  1. 提交任务的客户端把一组组待计算任务的输入编制成消息发送到 SQS 或 SNS 队列中
  2. SQS 消息可被  ECS 或 Lambda 处理, SNS 消息还能触发 Lambda,ECS/Lambda 完成实际的计算任务
  3. 结果可以保存到 Redis, S3 或别处, 如果提交任务端想要获取计算结果,可用 ID 来追踪

用 ECS 的好处是可以基于 SQS 的消息数进行 AutoScaling 配置,决定 Worker 的规模; 用 Lambda 适当的用 Concurrency 数来限定 Lambda 的实例数。

而 Python 的 Celery 让这一切变得更简单,它其实就是以上设计的一个集成方案。它以配置的方式选择使用任务队列(Broker), 结果存储方式(Backend), 让任务提交与 Worker 的代码实现简单化。 阅读全文 >>

RabbitMQ 初体验(安装,概念及应用)

之前工作中用过 JMS 的 IBM MQSeries, 自己试玩过 ActiveMQ, 再就是 Kafka, 再到 AWS 上的 SQS 等消息队列。打算调教一下 Python 的 Celery,它首推用 RabbitMQ 作为它的消息,当然也可选择 Redis 或 AWS 的 SQS,首先感觉有必要体验一下 RabbitMQ。

RabbitMQ 是一个 AMQP(Advanced Message Queuing Protocol) 的开源实现, 相关的实现产品还有 OpenAMQ, StormMQ, Apache Qpid, Red Hat Enterprise MRG, Microsoft Azure Service Bus 等,AMQP 与 JMS 还存在一些交集。

本文不打算介绍太多的 RabbitMQ 的一些概念,主要是体验一下如何安装,怎么发送和接受消息,初次体验就不直接上 Docker 了,用 Docker 根本不知道 RabbitMQ 是个什么东西,所以用一个 Ubuntu 20.04 虚拟机来一步步安装。

先用 Vagrant 准备一个虚拟机,Vagrantfile 文件内容如下 阅读全文 >>

小心 Python 函数默认参数的陷阱

Python 的函数参数支持默认值,这是本人一直喜欢的特性,Python 不支持方法重载,但默认参数可起到类似的效果,还不用写多个函数。现在支持默认参数的语言普遍的,像 C++, C#, Ruby, Groovy, PHP, Scala, JavaScript 等,Java 还不行。

但是特别要小心,Python 的函数默认值与其他的语言是不同的,直接违反了最直观的常识 -- 默认参数应该是省略就每次用同样的默认值,传的话就用传入的值。

当我在 IntelliJ IDEA 中写类似如下的代码

我的 SonarLint 插件就要抱怨了

说是

SonarLint: Change this default value to "None" and initialize this parameter inside the function/method
Default argument value is mutable

阅读全文 >>

Python 类实现的装饰器及简陋 REST API

学习了函数实现的 Python 装饰器后,关于装饰器的内容还没完。Python 装饰器还是属于元编程的范畴,一谈到元(Meta), 元编程,往往能用简单的方式实现比较神奇的效果 -- 小渣男的非死不可除外。Python 还允许用类来实现装饰器,原理上就是能让 Python 对象函数用,见之前的一篇 Python 对象当函数使用及动态添加方法。关键就是类实现 __call__ 函数,对象就变成 callable, 与函数的装饰器实现归纳起来就是:一个 Python 类型能不能用 @ 当作装饰器来用只需看它是否是 callable

而且因为有了类,带属性的装饰器也会更简单,装饰器的属性就是构造函数的参数。还是来看怎么用类重新实现前面的 my_decorator 装饰器 阅读全文 >>

Python 中带属性的装饰器

刚刚完成 由 Python 的 Ellipsis 到 *, /, *args, **kwargs 函数参数, 又回想起在 熟悉和应用 Python 的装饰器,关于带属性的装饰器一直未交代,安心不下来,Python 中带属性的装饰器用得非常普遍,如 Flask 的 @app.route('/')

我们一看到 Python 的装饰器(Decorator) 会很直截的与 Java 的注解(Annotation) 联系起来,其实除了都用 @ 符号外是存在很大区别的。正如它们被翻译成的中文名那样,Java 的注解在一定程度上就是一个注释,只要没有注解处理器处理它们就可以被忽略,Java 要用反射来处理注解。而 Python 的装饰器更象是代理,函数一旦被装饰后,调用目标函数时是无法挣脱装饰器函数的控制的,是硬核的。 阅读全文 >>