展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 数据库 > 编程开发 > 如何在 Python 中异步操作数据库?aiomysql、asyncpg、aioredis 使用介绍

如何在 Python 中异步操作数据库?aiomysql、asyncpg、aioredis 使用介绍

Python目前已经进化到了3.8版本,对操作数据库也提供了相应的异步支持。当我们做一个Web服务时,性能的瓶颈绝大部分都在数据库上,如果一个请求从数据库中读数据的时候能够自动切换、去处理其它请求的话,是不是就能提高并发量了呢。(编者注:原文写于2020年2月,当时最新为Python3.8,文章内容现在仍未过时)下面我们来看看如何使用Python异步操作MySQL、PostgreSQL以及Redis,以上几个可以说是最常用的数据库了。至于SQLServer、Oracle,本


如何在 Python 中异步操作数据库?aiomysql、asyncpg、aioredis 使用介绍

Python 目前已经进化到了 3.8 版本,对操作数据库也提供了相应的异步支持。当我们做一个 Web 服务时,性能的瓶颈绝大部分都在数据库上,如果一个请求从数据库中读数据的时候能够自动切换、去处理其它请求的话,是不是就能提高并发量了呢。

(编者注:原文写于 2020 年 2 月,当时最新为Python 3.8,文章内容现在仍未过时)

下面我们来看看如何使用 Python 异步操作 MySQL、PostgreSQL 以及 Redis,以上几个可以说是最常用的数据库了。至于 SQLServer、Oracle,本人没有找到相应的异步驱动,有兴趣可以自己去探索一下。

而操作数据库无非就是增删改查,下面我们来看看如何异步实现它们。

异步操作 MySQL

异步操作 MySQL 的话,需要使用一个 aiomysql,直接 pip install aiomysql 即可。

aiomysql 底层依赖于 pymysql,所以 aiomysql 并没有单独实现相应的连接驱动,而是在 pymysql 之上进行了封装。

查询记录

下面先来看看如何查询记录。

import asyncio
import aiomysql.sa as aio_sa
async def main():
# 创建一个异步引擎
engine = await aio_sa.create_engine(host="xx.xxx.xx.xxx",
port=3306,
user="root",
password="root",
db="_hanser",
connect_timeout=10)
# 通过 engine.acquire() 获取一个连接
async with engine.acquire() as conn:
# 异步执行, 返回一个  对象
result = await conn.execute("SELECT * FROM girl")
# 通过 await result.fetchone() 可以获取满足条件的第一条记录, 一个  对象
data = await result.fetchone()
# 可以将  对象想象成一个字典
print(data.keys())# KeysView((1, '古明地觉', 16, '地灵殿'))
print(list(data.keys()))# ['id', 'name', 'age', 'place']
print(data.values())# ValuesView((1, '古明地觉', 16, '地灵殿'))
print(list(data.values()))# [1, '古明地觉', 16, '地灵殿']
print(data.items())# ItemsView((1, '古明地觉', 16, '地灵殿'))
print(list(data.items()))# [('id', 1), ('name', '古明地觉'), ('age', 16), ('place', '地灵殿')]
# 直接转成字典也是可以的
print(dict(data))# {'id': 1, 'name': '古明地觉', 'age': 16, 'place': '地灵殿'}
# 最后别忘记关闭引擎, 当然你在创建引擎的时候也可以通过 async with aio_sa.create_engine 的方式创建
# async with 语句结束后会自动执行下面两行代码
engine.close()
await engine.wait_closed()
 loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

怎么样,是不是很简单呢,和同步库的操作方式其实是类似的。但是很明显,我们在获取记录的时候不会只获取一条,而是会获取多条,获取多条的话使用 await result.fetchall() 即可。

import asyncio
from pprint import pprint
import aiomysql.sa as aio_sa
async def main():
# 通过异步上下文管理器的方式创建, 会自动帮我们关闭引擎
async with aio_sa.create_engine(host="xx.xxx.xx.xxx",
port=3306,
user="root",
password="root",
db="_hanser",
connect_timeout=10) as engine:
async with engine.acquire() as conn:
result = await conn.execute("SELECT * FROM girl")
# 此时的 data 是一个列表, 列表里面是  对象
data = await result.fetchall()
# 将里面的元素转成字典
pprint(list(map(dict, data)))
"""
[{'age': 16, 'id': 1, 'name': '古明地觉', 'place': '地灵殿'},
 {'age': 16, 'id': 2, 'name': '雾雨魔理沙', 'place': '魔法森林'},
 {'age': 400, 'id': 3, 'name': '芙兰朵露', 'place': '红魔馆'}]
"""
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

除了 fetchone、fetchall 之外,还有一个 fetchmany,可以获取指定记录的条数。

import asyncio
from pprint import pprint
import aiomysql.sa as aio_sa
async def main():
# 通过异步上下文管理器的方式创建, 会自动帮我们关闭引擎
async with aio_sa.create_engine(host="xx.xxx.xx.xxx",
port=3306,
user="root",
password="root",
db="_hanser",
connect_timeout=10) as engine:
async with engine.acquire() as conn:
result = await conn.execute("SELECT * FROM girl")
# 默认是获取一条, 得到的仍然是一个列表
data = await result.fetchmany(2)
pprint(list(map(dict, data)))
"""
[{'age': 16, 'id': 1, 'name': '古明地觉', 'place': '地灵殿'},
 {'age': 16, 'id': 2, 'name': '雾雨魔理沙', 'place': '魔法森林'}]
"""
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

以上就是通过 aiomysql 查询数据库中的记录,没什么难度。但是值得一提的是,await conn.execute 里面除了可以传递一个原生的 SQL 语句之外,我们还可以借助 SQLAlchemy。

import asyncio
from pprint import pprint
import aiomysql.sa as aio_sa
from sqlalchemy.sql.selectable import Select
from sqlalchemy import text
async def main():
async with aio_sa.create_engine(host="xx.xxx.xx.xxx",
port=3306,
user="root",
password="root",
db="_hanser",
connect_timeout=10) as engine:
async with engine.acquire() as conn:
sql = Select([text("id, name, place")], whereclause=text("id != 1"), from_obj=text("girl"))
result = await conn.execute(sql)
data = await result.fetchall()
pprint(list(map(dict, data)))
"""
[{'id': 2, 'name': '雾雨魔理沙', 'place': '魔法森林'},
 {'id': 3, 'name': '芙兰朵露', 'place': '红魔馆'}]
"""
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

添加记录

然后是添加记录,我们同样可以借助 SQLAlchemy 帮助我们拼接 SQL 语句。

import asyncio
from pprint import pprint
import aiomysql.sa as aio_sa
from sqlalchemy import Table, MetaData, create_engine
async def main():
async with aio_sa.create_engine(host="xx.xx.xx.xxx",
port=3306,
user="root",
password="root",
db="_hanser",
connect_timeout=10) as engine:
async with engine.acquire() as conn:
# 我们还需要创建一个 SQLAlchemy 中的引擎, 然后将表反射出来
s_engine = create_engine("mysql+pymysql://root:root@xx.xx.xx.xxx:3306/_hanser")
tbl = Table("girl", MetaData(bind=s_engine), autoload=True
insert_sql = tbl.insert().values(
[{"name": "十六夜咲夜", "age": 17, "place": "红魔馆"},
 {"name": "琪露诺", "age": 60, "place": "雾之湖"}])
# 注意: 执行的执行必须开启一个事务, 否则数据是不会进入到数据库中的
async with conn.begin():
# 同样会返回一个  对象
# 尽管我们插入了多条, 但只会返回最后一条的插入信息
result = await conn.execute(insert_sql)
# 返回最后一条记录的自增 id
print(result.lastrowid)
# 影响的行数
print(result.rowcount)
# 重新查询, 看看记录是否进入到数据库中
async with engine.acquire() as conn:
data = await (await conn.execute("select * from girl")).fetchall()
data = list(map(dict, data))
pprint(data)
"""
[{'age': 16, 'id': 1, 'name': '古明地觉', 'place': '地灵殿'},
 {'age': 16, 'id': 2, 'name': '雾雨魔理沙', 'place': '魔法森林'},
 {'age': 400, 'id': 3, 'name': '芙兰朵露', 'place': '红魔馆'},
 {'age': 17, 'id': 16, 'name': '十六夜咲夜', 'place': '红魔馆'},
 {'age': 60, 'id': 17, 'name': '琪露诺', 'place': '雾之湖'}]
"""
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

还是很方便的,但是插入多条记录的话只会返回插入的最后一条记录的信息,所以如果你希望获取每一条的信息,那么就一条一条插入。

修改记录

修改记录和添加记录是类似的,我们来看一下。

import asyncio
from pprint import pprint
import aiomysql.sa as aio_sa
from sqlalchemy import Table, MetaData, create_engine, text
async def main():
async with aio_sa.create_engine(host="xx.xx.xx.xxx",
port=3306,
user="root",
password="root",
db="_hanser",
connect_timeout=10) as engine:
async with engine.acquire() as conn:
s_engine = create_engine("mysql+pymysql://root:root@xx.xx.xx.xxx:3306/_hanser")
tbl = Table("girl", MetaData(bind=s_engine), autoload=True)
update_sql = tbl.update().where(text("name = '古明地觉'")).values({"place": "东方地灵殿"})
# 同样需要开启一个事务
async with conn.begin():
result = await conn.execute(update_sql)
print(result.lastrowid)# 0
print(result.rowcount) # 1
# 查询结果
async with engine.acquire() as conn:
data = await (await conn.execute("select * from girl where name = '古明地觉'")).fetchall()
data = list(map(dict, data))
pprint(data)
"""
[{'age': 16, 'id': 1, 'name': '古明地觉', 'place': '东方地灵殿'}]
"""
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

可以看到,记录被成功的修改了。

删除记录

删除记录就更简单了,直接看代码。

import asyncio
import aiomysql.sa as aio_sa
from sqlalchemy import Table, MetaData, create_engine, text
async def main():
async with aio_sa.create_engine(host="xx.xx.xx.xxx",
port=3306,
user="root",
password="root",
db="_hanser",
connect_timeout=10) as engine:
async with engine.acquire() as conn:
s_engine = create_engine("mysql+pymysql://root:root@xx.xx.xx.xxx:3306/_hanser")
tbl = Table("girl", MetaData(bind=s_engine), autoload=True)
update_sql = tbl.delete()# 全部删除
# 同样需要开启一个事务
async with conn.begin():
result = await conn.execute(update_sql)
# 返回最后一条记录的自增 id, 我们之前修改了 id = 0 记录, 所以它跑到最后了
print(result.lastrowid)# 0
# 受影响的行数
print(result.rowcount) # 6
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

此时数据库中的记录已经全部被删除了。

整体来看还是比较简单的,并且支持的功能也比较全面。

异步操作 PostgreSQL

异步操作 PostgreSQL 的话,我们有两个选择,一个是 asyncpg 库,另一个是 aiopg 库。

asyncpg 是自己实现了一套连接驱动,而 aiopg 则是对 psycopg2 进行了封装,个人更推荐 asyncpg,性能和活跃度都比 aiopg 要好。

下面来看看如何使用 asyncpg,首先是安装,直接 pip install asyncpg 即可。

查询记录

首先是查询记录。

import asyncio
from pprint import pprint
import asyncpg
async def main():
# 创建连接数据库的驱动
conn = await asyncpg.connect(host="localhost",
 port=5432,
 user="postgres",
 password="zgghyys123",
 database="postgres",
 timeout=10)
# 除了上面的方式,还可以使用类似于 SQLAlchemy 的方式创建
# await asyncpg.connect("postgres://postgres:zgghyys123@localhost:5432/postgres")
# 调用 await conn.fetchrow 执行 select 语句,获取满足条件的单条记录
# 调用 await conn.fetch 执行 select 语句,获取满足条件的全部记录
row1 = await conn.fetchrow("select * from girl")
row2 = await conn.fetch("select * from girl")
# 返回的是一个 Record 对象,这个 Record 对象等于将返回的记录进行了一个封装
# 至于怎么用后面会说
print(row1)# 
pprint(row2)
"""
[,
 ,
 ]
"""
# 关闭连接
await conn.close()
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

以上我们演示了如何使用 asyncpg 来获取数据库中的记录,我们看到执行 select 语句的话,我们可以使用 conn.fetchrow(query) 来获取满足条件的单条记录,conn.fetch(query) 来获取满足条件的所有记录。

Record 对象

我们说使用 conn.fetchone 查询得到的是一个 Record 对象,使用 conn.fetch 查询得到的是多个 Record 对象组成的列表,那么这个 Rcord 对象怎么用呢?

import asyncio
import asyncpg
async def main():
conn = await asyncpg.connect("postgres://postgres:zgghyys123@localhost:5432/postgres")
row = await conn.fetchrow("select * from girl")
print(type(row))# 
print(row)# 
# 这个 Record 对象可以想象成一个字典
# 我们可以将返回的字段名作为 key, 通过字典的方式进行获取
print(row["id"], row["name"])# 1 古明地觉
# 除此之外,还可以通过 get 获取,获取不到的时候会返回默认值
print(row.get("id"), row.get("name"))# 1 古明地觉
print(row.get("xxx"), row.get("xxx", "不存在的字段"))# None 不存在的字段
# 除此之外还可以调用 keys、values、items,这个不用我说,都应该知道意味着什么
# 只不过返回的是一个迭代器
print(row.keys())# 
print(row.values())# 
print(row.items())# 
# 我们需要转成列表或者元组
print(list(row.keys()))# ['id', 'name', 'age', 'place']
print(list(row.values()))# [1, '古明地觉', 16, '地灵殿']
print(dict(row.items()))# {'id': 1, 'name': '古明地觉', 'age': 16, 'place': '地灵殿'}
print(dict(row))# {'id': 1, 'name': '古明地觉', 'age': 16, 'place': '地灵殿'}
# 关闭连接
await conn.close()
if __name__ == '__main__':
asyncio.run(main())

当然我们也可以借助 SQLAlchemy 帮我们拼接 SQL 语句。

import asyncio
from pprint import pprint
import asyncpg
from sqlalchemy.sql.selectable import Select
from sqlalchemy import text
async def main():
conn = await asyncpg.connect("postgres://postgres:zgghyys123@localhost:5432/postgres")
sql = Select([text("id, name, place")], whereclause=text("id != 1"), from_obj=text("girl"))
# 我们不能直接传递一个 Select 对象, 而是需要将其转成原生的字符串才可以
rows = await conn.fetch(str(sql))
pprint(list(map(dict, rows)))
"""
[{'id': 2, 'name': '椎名真白', 'place': '樱花庄'},
 {'id': 3, 'name': '古明地恋', 'place': '地灵殿'}]
"""
# 关闭连接
await conn.close()
if __name__ == '__main__':
asyncio.run(main())

此外,conn.fetch 里面还支持占位符,使用百分号加数字的方式,举个例子:

import asyncio
from pprint import pprint
import asyncpg
async def main():
conn = await asyncpg.connect("postgres://postgres:zgghyys123@localhost:5432/postgres")
rows = await conn.fetch("select * from girl where id != $1", 1)
pprint(list(map(dict, rows)))
"""
[{'age': 16, 'id': 2, 'name': '椎名真白', 'place': '樱花庄'},
 {'age': 15, 'id': 3, 'name': '古明地恋', 'place': '地灵殿'}]
"""
# 关闭连接
await conn.close()
if __name__ == '__main__':
asyncio.run(main())
  • 还是推荐使用 SQLAlchemy 的方式,这样更加方便一些,就像 aiomysql 一样。但是对于 asyncpg 而言,实际上接收的是一个原生的 SQL 语句,是一个字符串,因此它不能像 aiomysql 一样自动识别 Select 对象,我们还需要手动将其转成字符串。而且这样还存在一个问题,至于是什么我们下面介绍添加记录的时候说。

添加记录

然后是添加记录,我们看看如何往库里面添加数据。


import asyncio
from pprint import pprint
import asyncpg
from sqlalchemy.sql.selectable import Select
from sqlalchemy import text
async def main():
conn = await asyncpg.connect("postgres://postgres:zgghyys123@localhost:5432/postgres")
# 执行 insert 语句我们可以使用 execute
row = await conn.execute("insert into girl(name, age, place) values ($1, $2, $3)",
 '十六夜咲夜', 17, '红魔馆')
pprint(row)# INSERT 0 1
pprint(type(row))# 
await conn.close()
if __name__ == '__main__':
asyncio.run(main())

通过 execute 可以插入单条记录,同时返回相关信息,但是说实话这个信息没什么太大用。除了 execute 之外,还有 executemany,用来执行多条插入语句。

import asyncio
import asyncpg
async def main():
conn = await asyncpg.connect("postgres://postgres:zgghyys123@localhost:5432/postgres")
# executemany:第一条参数是一个模板,第二条命令是包含多个元组的列表
# 执行多条记录的话,返回的结果为 None
rows = await conn.executemany("insert into girl(name, age, place) values ($1, $2, $3)",
[('十六夜咲夜', 17, '红魔馆'), ('琪露诺', 60, '雾之湖')])
print(rows)# None
# 关闭连接
await conn.close()
if __name__ == '__main__':
asyncio.run(main())

注意:如果是执行大量 insert 语句的话,那么 executemany 要比 execute 快很多,但是 executemany 不具备事务功。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
数据库 编程开发 Python
相关文章 更多
精品专题 更多
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

IOS软件

正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

AI

正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

Mac软件 更多
SketchUp Pro macOS版
SketchUp Pro macOS版

SketchUp Pro 是面向建筑、室内、景观及产品设计工作的专业三维建模套件,提供直观的推拉建模、精准尺寸控制、二维文档制作、模型资源库、扩展插件和云端协作能力。Mac 用户可使用桌面建模器与 LayOut。

Twinmotion macOS版
Twinmotion macOS版

Twinmotion是Epic Games推出的实时三维可视化软件,主要服务于建筑、景观、室内设计、城市规划及施工展示。它可导入常见CAD、BIM和三维模型,利用材质、植被、人物、天气与灯光资源快速搭建场景。

Vectorworks Architect macOS版
Vectorworks Architect macOS版

Vectorworks Architect是一款面向建筑师、室内设计师及AEC团队的专业BIM设计软件,可在统一环境中完成概念草图、二维制图、三维建模、建筑信息管理、施工文档和效果展示,并支持IFC、Revit、DWG、SketchUp及点

Xcode macOS版
Xcode macOS版

Xcode 是苹果面向 Mac 提供的官方集成开发环境,将代码编辑、项目构建、SwiftUI 实时预览、设备模拟、自动化测试、断点调试、性能分析和应用分发整合在同一套工作流中,适合开发与维护 iPhone、iPad、Mac、Apple Wa

Adobe Acrobat Pro macOS版
Adobe Acrobat Pro macOS版

Adobe Acrobat Pro 是面向办公、法务、财务、教育及出版用户的专业PDF处理软件,可在Mac上创建、编辑、转换、合并和保护文档,并提供OCR文字识别、表单、批注、内容比较、敏感信息遮盖及电子签名功能。

Visual Studio Code macOS版
Visual Studio Code macOS版

Visual Studio Code 是微软提供的免费代码编辑器,支持 macOS,并为 Intel 与 Apple 芯片 Mac 提供适配版本。软件集代码编辑、调试、Git 源代码管理、集成终端和扩展市场于一体。

photoshop
photoshop

Photoshop 2026 是 Adobe 推出的专业图像处理与视觉设计软件,支持 Windows、macOS 和 iPad 等平台,广泛应用于摄影修图、电商设计、平面海报、数字绘画及视觉合成等创作场景。

Blender
Blender

Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

灵活计算器
灵活计算器

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

图几
图几

图几是一款适用于 macOS 的截图、标注与美化工具,支持离线操作保障隐私。界面整理和高频系统操作被放到一起考虑,桌面或窗口内容一多时,管理起来会更省心。

WINDOWS 更多
3dmax(3ds max)
3dmax(3ds max)

Autodesk 3ds Max 是一款专业的三维建模、动画与渲染软件,广泛应用于建筑可视化、游戏开发、影视动画、广告设计和产品展示等领域。

photoshop
photoshop

Photoshop 2026 是 Adobe 推出的专业图像处理与视觉设计软件,支持 Windows、macOS 和 iPad 等平台,广泛应用于摄影修图、电商设计、平面海报、数字绘画及视觉合成等创作场景。

Blender
Blender

Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

Windows 10
Windows 10

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

傲梅轻松备份
傲梅轻松备份

傲梅轻松备份是一款专业易用的数据备份软件,为重要数据提供安全保障。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

Mac
Wise Folder Hider Pro
Wise Folder Hider Pro

Wise Folder Hider Pro 是一款专业级文件和文件夹隐藏加密软件,为私密数据添加多重保护。高频操作更强调就近处理,浏览、整理和跨目录移动文件时,来回切换和重复点击都会少很多。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。