AWS Python Lambda 使用 Layer

使用 Python 书写 AWS Lambda 的一个好处就是能够在控制台中直接编辑源代码,非常方便进行快速验证测试 AWS 环境相关的。这只限于使用 AWS 为 Python Lambda 运行时提供的默认组件(比如 boto3),尚若需要在自己的 Python Lambda 中使用其他的组件(如 redis), 就不得不把自己的代码及依赖打成一个 zip 包再部署,这时候就无法在控制台直接编辑代码了,也只能坠入本地修改代码,重新打包上传测试的循环当中。

欲了解 Python Lambda 中除了 boto3 外还能直接使用别的什么组件,可点击此链接 https://gist.github.com/gene1wood/4a052f39490fae00e0c3 查看当前。该 gist 也还提供了代码 code to run in Lambda 来获得所有依赖。试了下在 Python Lambda 中,用通常的

help('modules')    # 或
help('modules package')

竟然连大名鼎鼎的 boto3 都无法列出来。

回到正题来,如果既想用第三方的依赖,又想要在控制台中直接编辑代码进行测试,是否有他法呢?有,那就是 AWS 在 2018 年 11 月推出的 Lambda 层。见 AWS Lambda Now Supports Custom Runtimes and Enables Sharing Common Code Between Functions, 这里的层除了能用来提供 Python 依赖,还许自定义运行时,如 C++ 或 Rust 等写 Lambda 都不是梦。

AWS 的服务就像个大口袋,何时偷偷的加添了什么服务,或出了什么新的我,不时关注它的 What's New with AWS 必是个好习惯。 阅读全文 >>

开启 Python 组件 Boto3 在 IDE 中的智能提示

在用 Python 编写 AWS 服务时,要用到 Boto 3 组件,而像 boto3.client('s3') 获得的对象只能被 IDE 识别为一个 BaseClient, 具体包含什么操作方法是在运行时由参数 s3 指示的基于 JSON 文件所描述的。因此 IDE 对 s3 = boto3.client('s3')s3 对象无法提供有效的智能提示,每次用 Boto 3 时不得不打开 Boto 3 的在线 API 文档来对照。长此以往,总觉麻烦且效率低下,有种一直摸着石头过河的感觉。那么,是否有办法让 IDE 智能提示出各种 boto3.client('<service>') 的实际操作呢?网上找了找,确实有这个需求,解决办法有

  1. botostubs: 与 boto3 API 保持更新(每三天),并支持众多 IDE, 试过在 IntelliJ IDEA 和 Visual Studio Code 中可用
  2. pyboto3: 上次更新在两年前, https://github.com/wavycloud/pyboto3, 只在 Python 2.7 下测试过
  3. autoboto: 需有智能提示,但改变了应用 Boto 3 组件的方式,不建议使用

本文重点推荐 botostubs, 下面会叙说具体理由,在进入正是之前,不妨来回顾一下直接使用 Boto 3 时没有好的智能提示的问题 阅读全文 >>

Python 常用日期处理 -- calendar 与 dateutil 模块

本文紧承上一篇 Python 常用日期处理,因制于篇幅的大小需求才临时分立新篇,这里要简单提到 calendar 和 dateutil 模块的使用,其中 calendar 是 Python 内置的。相比于上一篇而言,此处主旨会更明确一些,只记录三个应用案例,分别是

  1. 用 dateutil 灵活的解析 datetime 字符串
  2. 给定起始日期后的连续日期
  3. 给定起始日期后连续的月末日期

dateutil 灵活的解析 datetime 字符串

使用 Python 内容的  date 或 datetime, 构造它们的实例时需要逐个的传入年月日或时分秒,或者要调用  fromisoformat() 方法解析严格的字符串表示格式。而 dateutil.parser 的 parse() 方法就显得特别的聪明和随意,它可以智能的解析更丰富的字符串表示方式。详细的支持格式请参考官方文档的 parse examples,恐怕官方文档也未列举完全,只要觉得合理的时间字符串就可以尝试去解析。下方是一些例子 阅读全文 >>

Python 常用日期处理 -- 内置模块 datetime

仅以此篇记录一下个人常用的 Python 处理日期的库与函数,主要涉及的类库有 Python 自带的 datetime, timecalendar,以及第三方的 dateutil。说到日期处理基本上要覆盖的概念有 date, time, datetime, timezone, calendar, 时间的比较与差值,解析与格式化显示等。

在 datetime 模块中类之间的继承关系如下:

object
├── date
│      └── datetime
├── time
├── timedelta
└── tzinfo
         └── timezone

我们着重体验一下前面粗体显示的 datetime, date, time, timedelta 对象, timezone 也不是不重要,有时候也可能只需要处理本地时间。 阅读全文 >>

Python 对象当函数使及动态添加方法

继续阅读 《Python Tricks: The Book》,书中说到 "Objects Can Behave Like Functions", 就是把对象当成函数来调用,在普通对象后加个括号就能调用相应的 __call__ 函数。下面是书中的例子

class Adder:
    def __init__(self, n):
        self.n = n

    def __call__(self, x):
        return self.n + x

然后是应用类 Adder 的代码

plus_3 = Adder(3)
plus_3(4)  # 普通对象 plus_3 当成函数来用

上面 plus_3 是一个普能的对象,并非一个函数,但如果把它当成函数来看待,那么 plus_3(4) 就会去寻找相应的 __call__ 函数。 阅读全文 >>

Python 函数参数的拆解

本文为阅读 《Python Tricks: The Book》一书的 3.5 Function Argument Unpacking 的笔记与扩充理解。函数参数拆解是定义可变参数(VarArgs) *args 和 **kwargs 的反向特性。

*args 和 **kwars 是函数可定义一个形参来接收传入的不定数量的实参。

而这里的函数参数拆解是形参定义多个,在调用时只传入一个集合类型对象(带上 * 或 ** 前缀),如 list, tuple, dict, 甚至是 generator, 然后函数能自动从集合对象中取得对应的值。

如果能理解下面赋值时的参数拆解和 Python 3.5 的新增 * ** 操作,那么于本文讲述的特性就好理解了。

唯一的不同时作为参数的集合传入函数时必须前面加上 * 或 **, 以此宣告该参数将被拆解,而非一个整体作为一个函数参数。加上 * 或 ** 与 Java 的 @SafeVarargs 有类似的功效,最接近的是 Scala 的 foo(Array[String]("d", "e") : _*) 写法。参见:Java 和 Scala 调用变参的方式 阅读全文 >>

Python 集合的遍历,推导及 filter/map/reduce 操作

借鉴于其他多数语言中集合的 map/reduce 操作,也想总结一下在 Python 中如何对集合进行 map/reduce。而不是对于 Python 集合只会用简单的 for ... in 遍历,处于之间的是 Python 的  Comprehension 操作,更倾向于译作推导; 在 Scala 中也有类似的  for-comprehension 语法。

因此本文将涉及到三个方面的知识,基本的集合遍历操作,集合的推导,与 filter/map/reduce 操作。我无法写出诸如 掌握 Python 集体看这一篇就够了 的文章,但基本由本篇出发能了解到 Python 集合的基本遍历,转换操作。其余如切片,和更多能作用于 Python 集合的函数未有提及, 请查阅相关文档。

集合的基本遍历操作

这一块主要是复习功课, 希望由此熟练掌握常用的集合遍历操作方式 阅读全文 >>

Python 多线程编程

这几天一直浸淫在对 Python 的学习当中,对于一个更习惯 Java 语言的人来说,在接接触 Python 各种概念时会不停的与 Java 进行碰撞。譬如这里要说到的线程,Python 能如何像 Java 一样创建并执行单个线程,以及是否也能使用线程池来进行多作务的执行呢?

整个读完了《THE Quick Python Book》一书也只字未提多线程,然而对于有长时间的 IO 等待的程序,对于当今普及的多核以及核内超线程的 CPU 来说,不使用多线程来并行或并发处理任务是万万不能的,否则效率的差别是数量级的。

基于与 Java 多线程编程进行的比较,主要着力于两个问题:1)创建并执行新的线程,2)线程池中执行任务

创建并执行新的线程

默认的,代码是在主线程中执行,主线程名称为 MainThread。如果要创建一个子线程并执行需要用到模块 threading。下面的是基本的代码 阅读全文 >>

熟悉和应用 Python 的装饰器

Python 在语法上除了冒号与强制缩进外其实也没有太多令人眼前一亮的东西,倒是它的装饰器(Decorator) 值得玩味。初读 《THE Quick Python Book》一书,关于 Decorator(装饰器) 这一节匆匆而过,只是觉得它像 Java 注解一样的东西,没太细究。后来慢慢看到还是不少地方在用装饰器,如 Python 的属性 @property, @name_attr.setter, 还有 Flask 中用于定义路由的 @app.route('/') 等。

因此还是有必要花些功夫去更深入的了解 Python 的装饰器,从目前对装饰器的理解,它兼具 Java 的注解与代理的功能,而且比 Java 中自定义注解的处理与动态代理的实现要简单的多,甚至不需要特别牵涉到到面向方面的编程这么一个专门的概念。Python 的装饰器并非指的设计模式中的装饰器模式,Python 的装饰器主要还是关于代理,或叫方法拦截,切面的。

装饰器简单说来就是一个高阶函数,即一个函数作为另一个函数的参数,比如说函数 A 作为函数 B 的参数,然后函数 B 的实现有能力决定实际调用 A 的前后作点手脚,甚至压根不调用 A。由此,装饰器完全可以实现面向方面的 @Before, @After, @Around, @AfterReturning, @AfterThrowing 所有语义。

Python 中的函数像 JavaScript 的一样是头等对象(first-class objects),所以函数本身可以作为参数任意传递,一个函数也可以返回另一个函数。Python 的函数中还允许用相同的 def func():... 语法定义内部函数。 阅读全文 >>

Python 包管理及虚拟环境的应用(三: pipenv)

前两篇分别学习了 Python 如何进行依赖的管理,以及结合虚拟环境来使用 pip 进行依赖管理。而有人觉得把 virtualenv 与 pip 分开来操作太麻烦了,而且 requirements.txt 描述依赖的方式十分笨拙,所以在前两者之上创建了 pipenv, 也谈不上重新发明了轮子吧。

3. Pipenv: 新一代依赖管理与虚拟环境

倘若不是经由 virtualenv, venv 而来到 pipenv,没有对比也就无法体会到 pipenv 的妙处的。pipenv 在总结了 virtualenv/venv 的缺点之后由 Kenneth Reitz 于 2017 年 1 月发布的新型 Python 依赖管理器。

  1. 它不再需要单独用 virtualenv 和 pip,只要一条命令 pipenv 完成所有的事
  2. 不用手动管理 requirements.txt 文件,而是由  pipenv 自动维护 Pipfile 和 Pipfile.lock 文件
  3. 自动创建虚拟环境,并且虚拟环境与项目文件分离
  4. 更详尽的依赖图(例如 pipenv graph),像 mvn dependency:tree 那样显示依赖树
  5. 控制台下输出颜色更丰富

阅读全文 >>