0%

临近 618 年中大促,各大云服务商也会提供一些优惠。正好我三年前在腾讯云上买的一台 2 核 4G 的虚拟机到期了,看了一下腾讯云的优惠活动,下单了一台 2 核 4G 的的轻量应用服务器(一年期,288 元)。

轻量应用服务器一般都会提供一些常见的镜像(WordpressLAMP 等),我的目的不是建站,所以还是选了朴素的 Ubuntu18.04 的基础镜像。

下面大致介绍一下我配置服务器的过程(安装及配置方法基本来源于对应工具官网)。

配置密钥登录

轻量应用服务器默认是从腾讯云控制台直接登录到终端,可以将自己的公钥加到 ssh 配置里。

1
2
# Remote
cat PUBLIC_KEY >> ~/.ssh/authorized_keys

为了方便登录,可以配置自己主机的ssh config 文件,随后就可以通过ssh light命令登录到服务器。

1
2
3
4
5
6
# ~/.ssh/config

Host light
HostName 1.2.3.5
Port 22
User lighthouse
Read more »

最近公司越来越多的项目开始推动单元测试,而我在公司里很早就在进行单元测试实践。就用这篇文章作为一次内部技术分享的主题,同时也代表我自己对单元测试的认识和实践。

单元测试的概念

单元测试是软件测试的一种类型,测试对象是最基础的代码单元(函数、类、模块),属于白盒测试。在经典的测试金字塔中,单元测试处于最底层。

testPyramid

最简单的单元测试:

basic.png

Read more »

使用 Python 对数据进行压缩

之前在工作中遇到一个需求,需要在手机小程序端获取到微信小商店店铺的所有商品数据。由于当时我们没有在后台维护用户的商品数据,选择的解决方案是现场调用商品列表接口,然后缓存在 Redis 里。
鉴于 Redis 的内存还是比较宝贵的,而用户的商品数据(转化为 json 格式后)又是一些比较有规律的文本数据,比较适合进行数据压缩,于是我调研了一下 Python 中的数据压缩的方案。

zip标准库

Python 中有一个标准库zip,常用来处理 zip 格式文件,提供的函数和方法也更适合文件操作。在这个案例中我们的数据是通过 http 接口获取的,额外进行一些文件操作有些麻烦和多余,zip标准库并不适合这个场景。

zlib标准库

zlib是一个常用的压缩、解压库,使用了 deflate 算法。zipunzip工具背后其实用的就是zlib。Python 内置了zlib标准库,提供的接口也很简洁易用(zlib.compresszlib.decompress)。

1
2
3
4
5
import zlib
raw = b'abc' * 100
compressed = zlib.compress(raw)
print(f'compress ratio = {len(compressed)/len(raw):.2}') # compress ratio = 0.05
assert zlib.decompress(compressed) == raw
Read more »

前段时间遇到一个需要在本地开发环境定时执行某个脚本来同步数据的情景。

如果是线上业务的话,我一般会使用Celery Beat来执行定时任务。考虑到运行Celery Beat需要启动两个服务(celery workercelery beat),还要管理虚拟环境并编写 Python 代码,用在简单的定时任务执行场景过于复杂。

说起定时任务,首先想到的就是crontab。于是我调研了一下crontab的使用方法,成功配置了定时任务,也在这里简单的介绍一下。

crontab 简介

crontab(守护进程为crond)是类 unix 平台下的一个定时任务管理工具,可用于周期性执行定时任务。

Read more »

Node.js 的作者 Ryan Dahl 在 2018 年 JSConf EU 上发布了一篇演讲:10 Things I Regret About Node.js,讲述了他认为自己在设计 Node.js 时的十个(实际上演讲中只提到七个)失误,包括:没有坚持使用 Promise,使用了 GYP 构建系统,package.json 和 node_modules 的设计失误等。

在演讲中 Ryan Dahl 宣布了一个新项目:Deno,一个新的服务端 Javascript 运行时。经过两年多的发展,Deno 已经发布了 1.8 版本,也有了一个活跃的开发者社区。我们今天就来简单的了解一下 Deno。

Deno 简介

Deno is a simple, modern and secure runtime for JavaScript and TypeScript that uses V8 and is built in Rust.

Deno 使用 V8 引擎,由 Rust 构建,是一个简单、现代、安全的 Javascript 和 Typescript 运行时。

Deno 的主要特性有:

  • 默认安全。外部代码没有文件系统、网络、环境的访问权限,除非显式开启。

  • 支持开箱即用的 TypeScript 的环境。

  • 只分发一个独立的可执行文件 (deno)。

  • 有着内建的工具箱,比如一个依赖信息查看器 (deno info) 和一个代码格式化工具 (deno fmt)。

  • 有一组经过审计的标准模块,保证能在 Deno 上工作。

  • 脚本代码能被打包为一个单独的 JavaScript 文件。

Read more »

Python 3.10 版本还在开发之中,目前释出的 dev 版本实现了新语法特性 Structural Pattern Matching(PEP 634):可以利用match语句和case语句匹配对象的不同模式,并应用不同的行为。

我先前自己尝试体验了一下Structural Pattern Matching语法(使用pyenv安装dev版本 Python 3.10),感觉很好用的,并且有很大的发挥空间。

Structural pattern matching has been added in the form of a match statement and case statements of patterns with associated actions. Patterns consist of sequences, mappings, primitive data types as well as class instances. Pattern matching enables programs to extract information from complex data types, branch on the structure of data, and apply specific actions based on different forms of data.

官方介绍

语法

1
2
3
4
5
6
7
8
9
match subject:
case <pattern_1>:
<action_1>
case <pattern_2>:
<action_2>
case <pattern_3>:
<action_3>
case _:
<action_wildcard>

最简单的模式匹配

我们可以使用match case直接匹配字面量。

1
2
3
4
5
6
7
8
9
10
def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Something's wrong with the Internet"
Read more »

最近使用 FastAPI 框架开发了一个 WEB 服务。

为了充分利用 FastAPI 作为一个 ASGI 框架的原生异步支持特性,很多业务代码也改成了异步函数,并且使用了异步的 HTTP 库httpx和 MongoDB 的异步 Python drivermotor

由此带来的一个问题就是异步 Python 代码的单元测试的编写问题。

测试异步函数

编写测试代码

Python 的异步函数返回的是一个协程对象(coroutine),需要在前面加await才能获取异步函数的返回值,而只有在异步函数中才能使用await语句,这也意味着一般异步函数的测试代码本身也需要是一个异步函数。

1
2
3
4
5
6
async def add(a:int, b:int):
return a + b

async def testAdd():
ret = await add(1, 2)
assert ret == 3

运行测试代码

与 Javascript 不同,Python 的异步代码需要显示地运行在事件循环中。

Python3.7 以上的版本中可以直接调用asyncio.run函。

如果使用的是更早的 Python 版本,就需要指定一个事件循环对象来运行异步代码。

1
2
3
4
5
6
7
8
import asyncio

# Python3.7+
asyncio.run(testAdd())

# Python3.6
loop = asyncio.new_event_loop()
loop.run_until_complete(testAdd())
Read more »

最近创建了几个 Python 的开源项目(u-coreutilsauto-loggerfastapi-redis-session)。

我在这些项目中开始使用poetry工具进行依赖管理,体验还是相当不错的。

poetry 简介

Poetry是一个基于pyproject.toml的工具,利用poetry可以更加方便地进行 Python 项目的开发、构建、发布和依赖管理。

接下来通过一个例子来简单介绍一下 poetry 的使用。

初始化项目

我们将创建一个库greet,提供一个greet函数来输出”Hello, World”,代码和文件结构都很简单。

1
2
3
# project/greet/__init__.py
def greet(name:str='World'):
print(f'Hello, {name}')

project目录下运行poetry init(可以通过pip install -U poetry进行poetry工具的安装),会有很多提示信息用于确认项目的名称、版本、作者、协议、Python 版本,也可以在init过程中指定项目的依赖和dev依赖。

poetry init运行成功后,solution目录下会生成一个pyproject.toml文件。

可以手动设置一些项目的其他信息,例如仓库地址或者README文件的位置。

Read more »