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

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

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

集合的基本遍历操作

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

PostgreSQL 批量插入, 更新和合并操作

就在 2019 年 1 月份微软收购了 PostgreSQL 数据库的初创公司 CitusData, 在云数据库方面可以增强与 AWS 的竟争。AWS 的 RDS 两大开源数据库就是 MySQL(Aurora 和 MariaDB 是它的变种) 和 PostgreSQL。

而 PostgreSQL 跳出了普通关系型数据库的类型约束,它灵活的支持 JSON, JSONB, XML, 数组等类型。比如说字段类型可以是各种形式的数组,一维或多维。

create table t1(
    address varchar(5)[3],
    counter integer[3][3],
    schedule text[][]
)

上面只是认识了一下 PostgreSQL 这一亮眼的特性,本篇重点不在如何定义操作数组类型的字段,而是对于普通的非数组字段类型如何用与数组相关的 unnest 关键字进行记录的批量插入,更新以及合并操作。

在正式使用介入 unnest 之前先熟悉一下 PostgreSQL 的 upsert(update insert) 操作。受其他数据库的影响,总以后 PostgreSQL 也应该支持 merge into 语句,而且竟然 PostgreSQL 官方也有文档介绍 MERGE 有模有样的,然而试了一下根本就不支持 merge into 操作。 阅读全文 >>

用 AWS Secrets Manager 存储和管理密钥

目前我们在 AWS 上把密钥,API Key  等信息是存储在  AWS Systems Manager 的 Parameter Store 中,它只提供了用 KMS Key 加密存储字符串的功能,最大字符串大小是 4096 个字符,它是免费的。

最近发现 AWS 上有一个新的服务 AWS Secrets Manager(2018 年 4 月发布的),听起来用它来存储密钥信息更高大上些。它同样提供了用 KMS Key 加密存储字符串的功能,字符串最大也是 4096 个字符。从 AWS Web 控制台上看可配置用 Key/Value 的形式,其实本质也是存储为一个 JSON 字符串。

Secrets Manager 与 Parameter Store 更多的功能是能与 RDS 集成 -- 选择数据库收集数据库的配置信息(主机名,端口,实例等), 还有就是可配置定期更新密钥,这对一个安全的系统定期改密码很重要。对于定期更新密钥的未作深入研究,AWS Secrets Manager 本身知道如何轮换 RDS 数据库的密钥,其他的需要一个 Lambda 来支持。 阅读全文 >>

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. 控制台下输出颜色更丰富

阅读全文 >>

Python 包管理及虚拟环境的应用(二: virtualenv)

原本想在一篇之内覆盖到 Python 的包管理以及各类虚拟环境的应用,没想根本就是一发不可收拾,恐怕两篇都完不了,所以也要进行重构。这里只涉及到 Python 的虚拟环境 venv 和 virtualenv,至于标题的话,也不想再改了,只作一,二,三编号,必要时仍能连缀成长篇。最后一篇将单独学习 pipenv 的应用。

以下序号也是承接上一篇 Python 包管理及虚拟环境的应用(一)

2. Python 虚拟环境

关于创建 Python 项目的虚拟环境,有三个工具可用, venv, virtualenv, 以及后面单独要学到的 pipenv

  1. venv , 即 python3 -m venv 命令,Python 3.3 及新版本自带了,为 Python 3.4 及以后的版本创建的虚拟环境会有 pip 和 setuptools 命令
  2. virtualenv 需要单独安装,但是它支持 Python 2.7 和  Python 3.3+, 创建的虚拟环境中带有 pip, setuptools 和 wheel 命令
  3. 另外,pyvenv 脚本也可用来创建 Python 虚拟环境,不过它自 Python 3.6 不推荐使用,建议用 python3 -m venv 命令

阅读全文 >>

Python 包管理及虚拟环境的应用(一: pip)

话说 Python 的哲学之一就是: 用一种方法,最好是只有一种方法来做一件事。可以用 python -m this 或在  python 交互界面下 import this 看到 The Zen of Python 有一句:

There should be one-- and preferably only one --obvious way to do it.

然而 Python 在关于包管理(依赖管理)一事上却让人面临了众多的选择。

即使是 Java 日趋发展庞大的今天,包管理工具也没有如今的 Python 复杂,Java 的包管理工具经历了手工下载 jar 包,Maven, Ant+Ivy, Gradle, sbt, 但主流的也就 Maven 和 Gradle, 并且它们兼具项目构建的功能。

这里有一个 Python 包管理工具变迁的视频: Kenneth Reitz - Pipenv: The Future of Python Dependency Management - PyCon 2018。再更早的 Python 依赖管理的方式不说,视频中提到了 阅读全文 >>

Python 中的 urlencode 和 urldecode 操作

Web  编程中由于需要用 Form 或 URL 来传递参数,所以必然会有 urlencode 和 urldecode 的操作,Python Web 也不例外。Python 对 URL 的编解码操作提供了 urllib 模块,下面例子中所使用的 Python 版本是  3.6.7,不同的 Python 版本可能略有差异。

简面言之本文就是关于以下六个函数的使用,更多关于 urllib 的用法请自行进一步研究。

from urllib.parse import urlencode, parse_ql, quote, quote_plus, unquote, unquote_plus

为什么两个 urlencode 和  urldecode 操作会涉及到六个函数的应用呢,分别来讲述

1. urlencode

Python 的  urllib 直接提供了  urlencode 函数,它的操作数是一个字典 阅读全文 >>

Jackson 反序列化 "Y"/"N" 为相应的布尔值

JSON 表示布尔值标准的形式是 true  和  false,如果 Java 对应的类型是对象  Boolean,那么在 JSON 中也可以是  null。如果收到 JSON 数据是用 'Y'/'N', 或 'Yes'/'No' 来表示布尔值的,那么使用 Java 的 Jackson 库如何把它们反序列化为相应的布尔属性值呢?

如果按照 JSON 规范必须把内容中的布尔值全部转换为 true 或 false, 然而再反序列化,否则需要定制 Boolean 类型的反序列化类,可应用到全局的 boolean 类型,或指派给特定的 boolean 类型属性。

如果尝试反序列化 Y, 或 N 为 Java 的 boolean 值,会有只接受  true 或 false 的异常:

com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.lang.Boolean from String "Y": only "true" or "false" recognized

具体步骤是: 阅读全文 >>