部署到不同环境的应用会使用到各自的配置,如 Dev, QA, Stg, Prod 有自己的数据库等资源。Spring Boot 可采用 Profile 对应不同的环境,不同 Profile 选择自己的配置文件application-${profile}.properties。本人还是偏爱在同一个文件中分组配置,容易查错与编辑,类如在 application.properties 文件中以下面的方式1db.host=aaa 2%dev.db.host=bbb 3%prod.db.host=ccc
那么在 Python 的项目中应该如何针对不同环境进行配置呢?大概有以下几种- 不同环境的 Config 类
- YAML 文件
- TOML 文件
- JSON 文件
- INI 文件
- dotenv(.env) 文件
第一种方式是本人推荐的,其他的方式只是在不同格式的配置文件中,按环境组织不同的配置值,其他方式的不同配置读入内存中基本是体现为字典变量。在 Python 配置中要支持像配置的 placeholder(像 ${host} 还需自己实现。 Read More
[latexpage]计算距离的目的也是为了确定两个向量的相似度,这里的向量可以是纯数学的数组,或者是一系列带有某些可量化特征值的物件。写作本文的原由是需要用 Numpy 计算两个实际对象的相似度,实现代码非常简单,因此更不能满足于此,借此机会多多了解下向量之间距离和相似度的概念,还回顾下一些相关的数学知识。
计算两个向量的相似度有许多的方法,如- 欧氏距离(Euclidean Distance): 点间直线距离,数值越小越相似
- 夹角余弦(Cosine): 余弦相似度(Cosine Similarity),计算两个向量之间的夹角,值在 -1 ~ 1 之间
- 曼哈顿距离(Manhattan Distance): 点间在坐标系上的绝对轴距总和
- 切比雪夫距离(Chebyshev Distance): 像国际象棋中的王从一格子到另一个格子间的距离
- 标准化欧氏距离(Standardized Euclidean distance): 先对各个分量进行标准化,再求欧氏距离
- 其他距离和相关系数,如马氏距离(Mahalanobis Distance), 兰氏距离(Lance Williams Distance); 皮尔逊相关系数(Pearson Correlation Coefficient), 杰卡德相似系数(Jaccard similarity coefficient)
本文主要关注到欧氏距离和余弦相似度这两个数值的求解上。 Read More
在阅读《HTTP/2 in Action》的 HTTPS 一节后,不觉一脚踏入到非对称加密这一领地而不能自拔。与非对称加密相对应的是对称加密,有点像是由一把钥匙反锁的门,只能用同一把钥匙打开; 而非对称加密是用一把钥匙反锁门,但只能用另一把特定的钥匙才能打开它,锁门的叫做公钥,开门的叫做私钥。
在此之前我理解的非对称加密以为是像 MD5 那种摘要(Digest), 由明文生成的 MD5 摘要信息是无法还原出原始数据的,谬以为那就是所谓的非对称。
1976 年,两位美国计算机学家 Whitefield Diffie 和 Martin Hellman 提出了非对称加解密的的构思。1977 年三位数学家 Ron Rivest, Adi Shamir 和 Leonard Adleman 实现了非对称加密算法,即 RSA,取自这三个的姓的首字母
具体的 RSA 算法原理可参考阮一峰的两篇网络日志:RSA算法原理 (一) 和 RSA算法原理 (二), 大致就是通过互质的两个数,计算欧拉函数, 模反元素,最终算法公钥和私钥,公钥加密的数据只能用用私钥解密,以当前的算力,只要 RSA 的密钥足够长,如 1024 位以上,私钥是无法通过公钥推断出来的。 Read More- 在学习 Python 3.10 新特性时,其中有个类型别名(TypeAlias), 所举的例子是
1StrCache = 'Cache[str]' # a type alias<br /> 2LOG_PREFIX = 'LOG[DEBUG]' # a module constant
可写成1StrCache: TypeAlias = 'Cache[str]' # a type alias<br /> 2LOG_PREFIX = 'LOG[DEBUG]' # a module constant
这让 StrCache 更像是一个类型别名,而不是一个看起来明显就是Cache[str]的字符串变量(实际上它确实是)。
本文不在 TypeAlias 本身,而是从Cache[str]能看出 Python 似乎也能支持像 Java 那样的泛型, 就像 Python 内置支持的 List[str] 或 list[str] 那样。
那么来看 Python 怎么去实现一个只能放入字符串的Cache[str]Cache, 而不能放入别的类型。 Read More
Python 不支持函数重载,在同一个模块中声明同名方法不会报错,只会不停的覆盖,无论参数个数是否不同,最终只会保留最后一个函数1foo = 100 2 3def foo(a): 4 print('foo(a)') 5 6def foo(a, b): 7 print('foo(a, b)') 8 9def foo(a: str): 10 print('foo(a: str)') 11 12foo([8]) 13print(globals()['foo']) 14foo(3, 5)
输出 Read More- 使用 Python 就难免要应对到不同数据库连接的问题,Python 目前也没有 Java 使用 JDBC 瘦客户端驱动那么方便。本人在用 Python 连接 SQL Server 时经常还是会有些问题,此文只着力于如何用 Python 连接 DB2 和 Oracle 数据库。
从本文中我们将会学到- Python 围绕着 ibm_db 来操作 DB2
- 以 Python DB-API 2.0 规范来操作 DB2
- cx_Oracle Python 库 + Oracle Instant Client 操作 Oracle
- 用 Oracle 的 SID 还是 Service Name 来连接数据库
- Python 中借助 JayDeBeApi 使用 JDBC 驱动来操作数据库(以 Oracle 为例)
- 从 JayDeBeApi 中我们了解到 JPype 有助于我们在 Python 中调用 Java
Python 操作 DB2
连接 DB2 数据库要简单的多,只要安装 ibm-db 库 Read More
之前工作中用过 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文件内容如下 Read More
学习了函数实现的 Python 装饰器后,关于装饰器的内容还没完。Python 装饰器还是属于元编程的范畴,一谈到元(Meta), 元编程,往往能用简单的方式实现比较神奇的效果 -- 小渣男的非死不可除外。Python 还允许用类来实现装饰器,原理上就是能让 Python 对象函数用,见之前的一篇 Python 对象当函数使用及动态添加方法。关键就是类实现__call__函数,对象就变成callable, 与函数的装饰器实现归纳起来就是:一个 Python 类型能不能用 @ 当作装饰器来用只需看它是否是callable。1class Duck: 2 def __call__(self): 3 print('quack') 4 5duck = Duck() 6print(callable(duck)) # True 7duck()
而且因为有了类,带属性的装饰器也会更简单,装饰器的属性就是构造函数的参数。还是来看怎么用类重新实现前面的my_decorator装饰器 Read More
刚刚完成 由 Python 的 Ellipsis 到 *, /, *args, **kwargs 函数参数, 又回想起在 熟悉和应用 Python 的装饰器,关于带属性的装饰器一直未交代,安心不下来,Python 中带属性的装饰器用得非常普遍,如 Flask 的@app.route('/')。
我们一看到 Python 的装饰器(Decorator) 会很直截的与 Java 的注解(Annotation) 联系起来,其实除了都用@符号外是存在很大区别的。正如它们被翻译成的中文名那样,Java 的注解在一定程度上就是一个注释,只要没有注解处理器处理它们就可以被忽略,Java 要用反射来处理注解。而 Python 的装饰器更象是代理,函数一旦被装饰后,调用目标函数时是无法挣脱装饰器函数的控制的,是硬核的。 Read More
早先对 Python *args, **kwargs 参数有所了解,也知道参数列表中的/表示 Positional Only,*很少见。然而在使用 FastAPI 时看到路由函数中表示默认值采用了...的方式又重新激发起我对 Python 函数参数的*,/,*args, 和**kwargs的兴趣。
如 FastAPI 官方文档 Request Forms and Files 中的@app.post("/files/")
默认值的
async def create_file(file: bytes = File(...), fileb: UploadFile = File(...), token: str = Form(...)):File(...),Form(...), 起初还以为...只是真正意义上的省略号,使用时需传入适当的参数,后来发现...居然是一个 Python 实实在在的内置对象。 Read More