Python async, await 的理解与使用

关于 Python 中 async, await 关键字的一些知识在去年的一篇 探索 Flask 对 asyncio 的支持 有讲到,一直没在实际上用过它们,所以基本上也就忘干净了。随着 Flask 2 加入了 async 的特性,以及 FastAPI 从一开始支持 async, 又觉得有必要重新温习一下 Python 中如何使用 async, await 关键字了。

注:由于 Flask 支持了 async, 号称 async 化 Flask 的  Quart 项目开始变得无足轻重了。

本文主要的学习材料是在 YouTube 上的一个视频 Fear and Awaiting in Async (Screencast), 其中用 Python REPL 以 Live 的形式展示,对 async, await 关键字循序渐进的讲解。

如今不少语言都支持 async, await 关键字,如 C#, JavaScript, Kotlin, Rust 等,还有今天的主角 Python。而 Java 仍然很重视函数返回值的意义,未支持 async, 只能显式的返回 Future/CompletableFuture, 而且自己控制如何在线程池中执行。 阅读全文 >>

Flask 应用集成 Swagger UI

成熟的 Web  API 框架总有一款 API 文档与之伴随,当前最知名的莫过于支持 Open API 的 Swagger 了。Python 的 Flask 框架支持 Swagger UI 也有几条路子

  1. Flasgger : 好像是 flask-swagger 的 fork
  2. flask-swagger: 许久未更新了,不用考虑
  3. flask-restful-swagger: 到目前也两年未更新了
  4. Flask-RESTPlus 的 Swagger 特性: 真需要用到 Flask-RESTPlus 就可以用它

单纯用 Flask 构建 API 的话,细数起来也就 Flasgger 比较合适,如果甩开 Flask 而用 FastAPI 的话,就不用操心 Swagger 了,因为 FastAPI 原生的支持 Swagger。

本文中我们将体验如何使用 Flasgger, 关于使用方法,在它源码的 README.md 已经描述的很清楚了。Flasgger 提供了以下几种主要的使用方式 阅读全文 >>

逐步理解 Flask 的 Blueprint(蓝本)

Python 的 Flask 框架能让我们快速的建立一个轻量级的 Web 或 REST API。对于小应用由一个 @app 装饰一撸到底就行,当项目稍具规模或要更清晰就要考虑模块化,于是来到了我们今天的话题,首先是

为什么需要 Blueprint?

比如说我们一定超级简单的 Flask 应用 main.py 的代码如下:

阅读全文 >>

Terraform 的变量使用及赋值规则

本人在 AWS 上建立基础架构的时候倾向于用 Terraform, 而不是 AWS 自家的 CloudFormation。倒不是因为 Terraform 支持多种类型的 Provider,而是它能模块化,不同项目共享 AWS 资源时也更方便。而使用 CloudFormation 的话,一不小心就会写出一个超大的 YAML 文件来,要使用共同的 AWS 资源时,谁来创建是个不小的问题。CloudFormation 稍值得称道的地方也就是有一个可视化的  Stack,但把  Terraform 执行的 state 存到 S3 也不差。使用 Terraform 还有一个最享受的地方就是它的官方文档组织的非常清晰。

出品 Terraform 的公司 HashiCorp 秉持着 Infrastructure as Code,近日在忙着 IPO, 估值在 $13B, Ticker 将为 HCP(该链接直接可用时便以上市),介时也值得关注一下。扯远了,回到日常使用 Terraform 的变量上来。

本文直接参考自 Terraform 官网的 Input Variables。不管英文好不好都应该读原文去理解 Terraform 变量的详细使用方法。这里主要是了解各种输入变量的方式,以及验证一下当同时用多种方式输入重复的变量时,以谁为最终的结果。 阅读全文 >>

SpringBoot2 应用 Axis 1.4 开发 WebService

有了前一篇 应用 Axis 1.4 开发 WebService 的对 Axis 1 较为深刻的理解后,现在正式给古老的 Axis 1.4  拉个伴,那就是 SpringBoot2。SpringBoot2 + Axis 1 的主要工作就是把 Axis 的 web.xml 用 SpringBoot2 的方式进行转述。

在 SpringBoot 中用 Axis 1 后,有两个特性不再支持

  1. 不再支持 jws 即时发布 Web Service,不能直接搬用 url-pattern *.jws,没继续深究,实际中希望这么部署的方式用得较少
  2. 不再支持 SOAPMonitorService,它是一个 Java Applet,  Java Applet 在新版的 JDK 中已被移除,早就不推荐使用了

在 SpringBoot 中配置 Servlet 或 ServletListener 有两种方式

  1. ServletRegistrationBean/ServletListenerRegistrationBean
  2. @WebServlet/@WebListener

spring-boot-starter 引入了 log4j-to-slf4j, jul-to-slf4j, 所以不需要配置 log4j.properties, 需要的话可用 logback.xml 配置日志输出。 阅读全文 >>

应用 Axis 1.4 开发 WebService

Axis 1 的最后一个版本还是 2006-04-22 发布的 1.4 Final 版,当前的版本是  Axis 2, 即于  2021-08-01 发布的  Axis v1.8.0 版本。想想在  2006 年 4 月份,软件开发是一种什么样的景象,JDK 5 于 2004-09-30 发布,同年 12 月 12 日 JDK 6 才出来, Spring 还是 1.x 的版本。那时候仍是 EJB 兴旺的年代,微服务概念的出现还有等好多年。

那为什么还要学习 Axis 1.4 呢?目的就是为了放弃,先前的 Axis 1.4 的项目不稍加理解,怎么能顺利的过度到 Axis 2 呢?要说眼下更好的用来开发 SOAP WebService 的库应该首选 Apache CXF。本来拟定的文章标题的 Springboot2 应用 Axis 1.4 开发 WebService, 但一发挥就用力过猛,只得下回另立新篇来再加上 Springboot2 了,因此本篇就是为 SpringBoot2 与 Axis 1 的结合铺路的。

什么是 SOAP,Simple Object Access Protocol, 简单对象访问协议,一种 XML-RPC 的实现。谁都敢号称简单,与当今的 REST API 一对照,任何人都会觉得 SOAP 是把一个远程调用搞得无比的复杂。SOAP 有 1.1 和 1.2 两个版本,现在提 SOAP 基本就是 SOAP 1.2 的代名词。另外,SOAP 1.2 开始也承认不简单,不再明确为 Simple Object Access Protocol 的缩写,而叫做 Messaging Framework (Second Edition)。 阅读全文 >>

mvn 命令上传文件到 Maven 仓库

针对一个 Maven 的 Java 项目,我们执行 mvn deploy 命令时想要把生成的 jar 包上传到 Maven 仓库(本文将使用私有的 Nexus 仓库)中去。所要用到的插件 Maven Deploy Plugin,本文实际就是讲述如何用该插件上传 jar 包到 Maven  仓库,更多用法请参考该插件的官方文档。

本文关键性的两个配置文件是 pom.xml 和 settings.xml。前者配置仓库的地址,后者中配置用户名和密码。要确定 Maven 使用了哪个 settings.xml 文件,用 mvn -X 查看,比如下面的输出

[DEBUG] Reading global settings from /usr/local/Cellar/maven/3.8.3/libexec/conf/settings.xml
[DEBUG] Reading user settings from /Users/yanbin/.m2/settings.xml

Maven 还允许在执行 mvn 命令时用  -s 或 --settings 参数指定 settings.xml 文件,如 mvn deploy --settings settings.xml

所以对于 settings.xml 文件的修改,可修改全局的,用户的或参数 --settings 指定的。 阅读全文 >>

AWS Assume IAM role 的使用

AWS 要授权给他人访问指定资源有哪几种方式呢?

  1. 创建一个 AWS 帐号让别人用,那是 AWS 干的事
  2. 在自己帐号下创建一个用户,把 Access Key ID 和 Secret Access Key 告诉别人。可为该用户限定权限,但任何获得那两个 Key 的人都能使用该用户。
  3. 创建一个 IAM Role, 并指定谁(帐号或 Role) 能以该 Role 的身份来访问。被 Assume 的 Role 可限定权限和会话有效期。

用 Assume Role 的方式具有更高的安全可控性,还不用维护 Access Key ID 和 Secret Access Key。比如在构建和部署时通常是有一个特定的 Account, 然后 Assume 到别的 IAM Role 去操作资源。

本文将详细介绍在帐号 A 创建一个 IAM Role(标注为 R) 并分配一些权限,然后允许另一个帐号 B 以 IAM Role - R 的身份来访问帐号 A 下的资源。IAM Role 将用 awscli 来创建,Assume Role 的过程用 awscli 和 boto3 Python 代码两种方式来演示。 阅读全文 >>

构建 AWS Lambda Python Docker 镜像

AWS 的 Lambda 在 2020-12-01 开始支持用 Docker 镜像存放代码,见 New for AWS Lambda - Container Image Support。AWS Lambda 最初的对发布包的限制是 50M, 解压后(因为执行前需要解压缩)不能超过 250M,对于压缩比小于 1/5 的包来说,要突破 50M 部署包的限制就要用 2018-11-29 推出的层(layer), 即把 Lambda 的依赖可以组织为层,每个 Lambda 可引用最多 5 个层,但最终 Lambda 加上层所解压后的大小仍然有 250 M 的限制。

对于使用了大量依赖的 Lambda,比如 Python 中用了 Pandas 之类的数学分析包,250M 的大小是不够的,所以才有了 Docker 镜像化的 Lambda, 镜像的大小限制一下蹦到 10G,要构建出一个 10G Lambda 用的 Linux 镜像, 那绝对是个巨兽,至少目前是超越我的想像力,除非往里面塞入大量的业务数据。关于 Lambda 有哪些限制,请参阅 Lambda quotas

介绍完 Lambda 引入 Docker 镜像的背景后,本文接下来只关注如何构建一个 Python Lambda 镜像,对于如何部署 Docker 化的 Lambda, 不在本文的范围之内。主要的参考文档为 AWS Lambda 官方的 Deploy Python Lambda functions with container images. 阅读全文 >>

创建和发布自己的 Python 包到 PyPI 上

像 Java 可发布包到 Maven 仓库,NodeJS 发布包到 NPM 一样,我们也可以创建自己的 Python 包并发布到 PyPI 仓库中去。或者内部使用的包,只须发布到私有的 Nexus 服务器上。

本文中的例子将创建一个 Python 包 bounded-executor, 并发布到 PyPI 上。为什么创建这个包呢?原因是直接用 Python 的 ThreadPoolExecutor 或  ProcessPoolExecutor 来提交任务的话,任务的等待队列是没有边界的,这就会造成因提交任务过快而使得内存爆满。本包最为合适的名称应该是 bounded-pool-executor, 可是名字已被他人使用,但此外的实现有所不同,ThreadPoolExecutor 用 Queue(maxsize) 来控制,而 ProcessPoolExceutor 用 BoundedSemaphore 来控制。

我们以经典的 Python 工程目录结构为例,构建的核心是执行 setup.py 中的 setup 函数,由此来理解 setup 的最主要配置与关键命令做了些什么。这样有助于我们理解其他的 Python 包管理工具的底层行为,从中我们可以对比 poetry 的 build, install, 和 publish 命令。 阅读全文 >>