一、catalogue 库概述
catalogue 是一款专为 Python 设计的轻量级对象注册与管理库,核心作用是实现函数、类、实例等对象的集中注册、分类存储与快速调用,底层基于字典与装饰器实现无侵入式绑定,无需复杂配置即可完成对象映射。其优点是体积小巧、无第三方依赖、使用简洁、适配任意 Python 项目,缺点是仅专注于对象注册,不具备数据校验、动态加载等扩展功能。该库采用 MIT License,开源免费可商用。

二、catalogue 库安装方法
catalogue 作为纯 Python 实现的轻量库,不依赖任何额外包,通过 pip 即可快速完成安装,适配 Python 3.6 及以上所有版本,安装命令如下:
pip install catalogue
安装完成后,可在 Python 交互环境中导入验证,无报错即代表安装成功:
import catalogue
# 无报错则安装正常
三、catalogue 库核心使用方式
3.1 基础注册与调用
catalogue 最核心的功能是通过装饰器完成对象注册,无需修改原函数或类的逻辑,即可将其加入指定命名空间,后续通过统一接口调用。
首先创建注册器,指定命名空间名称,再使用 @registerer.register 装饰器绑定对象:
# 1. 创建注册器,命名空间为 "tools"
tool_registry = catalogue.create("tools")
# 2. 注册普通函数
@tool_registry.register("print_hello")
def hello():
"""简单的问候函数"""
print("Hello, catalogue!")
# 3. 注册带参数的函数
@tool_registry.register("add_num")
def add(a, b):
"""数值加法函数"""
return a + b
# 4. 通过注册名称调用对象
# 调用 hello 函数
tool_registry.get("print_hello")()
# 调用 add 函数并输出结果
result = tool_registry.get("add_num")(3, 5)
print("3 + 5 =", result)
代码说明:
catalogue.create()用于创建指定命名空间的注册器,不同命名空间相互隔离,避免命名冲突;@registerer.register(name)装饰器将被装饰对象绑定到注册器,name为唯一标识;registerer.get(name)可根据标识获取注册对象,直接调用即可执行原函数逻辑。
运行结果:
Hello, catalogue!
3 + 5 = 8
3.2 类与实例注册
catalogue 不仅支持函数注册,还能注册类、类方法、实例对象,适配面向对象编程场景。
# 创建新的注册器,命名空间为 "classes"
class_registry = catalogue.create("classes")
# 注册类
@class_registry.register("Calculator")
class Calculator:
def __init__(self, name):
self.name = name
def multiply(self, x, y):
return x * y
def __str__(self):
return f"计算器: {self.name}"
# 获取注册的类并创建实例
CalcClass = class_registry.get("Calculator")
calc_instance = CalcClass("数学计算器")
print(calc_instance)
# 调用实例方法
print("4 * 6 =", calc_instance.multiply(4, 6))
# 直接注册实例对象
@class_registry.register("default_calc")
default_calc = CalcClass("默认计算器")
# 调用注册的实例
instance = class_registry.get("default_calc")
print("5 * 7 =", instance.multiply(5, 7))
代码说明:
- 类注册后,可通过
get()获取类本身,再实例化使用; - 实例可直接注册,无需重复创建,适合单例对象管理;
- 注册逻辑完全不侵入类的定义,保持原有代码结构不变。
运行结果:
计算器: 数学计算器
4 * 6 = 24
5 * 7 = 35
3.3 多命名空间与层级注册
catalogue 支持创建多个独立命名空间,还可通过层级路径实现细分管理,适合大型项目中模块拆分。
# 创建多层级注册器:主命名空间 "app",子命名空间 "auth"
auth_registry = catalogue.create("app", "auth")
# 创建另一个子命名空间 "api"
api_registry = catalogue.create("app", "api")
# 注册认证相关函数
@auth_registry.register("login")
def login(username, password):
return f"用户 {username} 登录成功"
@auth_registry.register("logout")
def logout():
return "用户退出登录"
# 注册 API 相关函数
@api_registry.register("get_user")
def get_user(uid):
return {"id": uid, "name": "测试用户"}
# 跨命名空间调用
print(auth_registry.get("login")("admin", "123456"))
print(api_registry.get("get_user")(1001))
# 查看所有注册项
print("auth 注册项:", list(auth_registry.keys()))
print("api 注册项:", list(api_registry.keys()))
代码说明:
catalogue.create(*names)可传入多个字符串,创建层级化命名空间;- 不同层级注册器相互独立,即使注册名称相同也不会冲突;
registerer.keys()可获取当前注册器内所有对象的标识,方便遍历管理。
运行结果:
用户 admin 登录成功
{'id': 1001, 'name': '测试用户'}
auth 注册项: ['login', 'logout']
api 注册项: ['get_user']
3.4 注册元数据与自定义属性
catalogue 支持在注册时添加自定义元数据,方便记录对象描述、作者、版本等附加信息,丰富注册对象的管理能力。
# 创建注册器
meta_registry = catalogue.create("meta_tools")
# 注册时传入元数据
@meta_registry.register("data_filter", author="test", version="1.0", desc="数据过滤工具")
def filter_data(data_list, condition):
return [item for item in data_list if condition(item)]
# 获取注册对象及元数据
func = meta_registry.get("data_filter")
meta = meta_registry.get_meta("data_filter")
print("函数对象:", func)
print("元数据:", meta)
# 使用注册函数
data = [1, 2, 3, 4, 5, 6]
filtered = func(data, lambda x: x % 2 == 0)
print("过滤偶数:", filtered)
代码说明:
register()可接收任意关键字参数作为元数据,自动存储;registerer.get_meta(name)专门用于获取对象的元数据,不影响原对象调用;- 元数据适合用于插件描述、配置记录、文档自动生成等场景。
运行结果:
函数对象: <function filter_data at 0x000001234567890>
元数据: {'author': 'test', 'version': '1.0', 'desc': '数据过滤工具'}
过滤偶数: [2, 4, 6]
3.5 遍历与检查注册对象
在实际项目中,常需要遍历所有注册对象或检查对象是否存在,catalogue 提供了简洁的接口实现该功能。
# 创建注册器并注册多个对象
check_reg = catalogue.create("check_demo")
@check_reg.register("func1")
def func1(): pass
@check_reg.register("func2")
def func2(): pass
@check_reg.register("func3")
def func3(): pass
# 检查对象是否存在
print("func1 是否存在:", "func1" in check_reg)
print("func4 是否存在:", "func4" in check_reg)
# 遍历所有注册对象
for name, obj in check_reg.items():
print(f"注册名称: {name}, 对象: {obj}")
# 获取所有注册名称
print("所有注册名称:", list(check_reg))
# 清空注册器(可选)
check_reg.clear()
print("清空后注册数量:", len(check_reg))
代码说明:
- 注册器支持
in关键字判断对象是否存在,语法符合 Python 原生习惯; items()可遍历所有名称与对象,list(check_reg)直接获取所有名称;clear()用于清空注册器,适合动态重置场景。
运行结果:
func1 是否存在: True
func4 是否存在: False
注册名称: func1, 对象: <function func1 at 0x000001234567890>
注册名称: func2, 对象: <function func2 at 0x000001234567891>
注册名称: func3, 对象: <function func3 at 0x000001234567892>
所有注册名称: ['func1', 'func2', 'func3']
清空后注册数量: 0
四、实际项目应用案例
4.1 插件化工具平台
在中小型项目中,常需要实现插件化功能,无需修改主程序即可新增功能,catalogue 是实现该需求的最简方案。
# 主程序:插件注册中心
plugin_registry = catalogue.create("my_app", "plugins")
# 插件1:文本处理
@plugin_registry.register("text_upper")
def to_upper(text):
return text.upper()
# 插件2:数字统计
@plugin_registry.register("num_count")
def count_numbers(num_list):
return{"sum": sum(num_list), "max": max(num_list), "min": min(num_list)}
# 插件3:时间格式化
@plugin_registry.register("time_format")
def format_time(timestamp):
from datetime import datetime
return datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S")
# 主程序调用逻辑
def run_plugin(plugin_name, *args, **kwargs):
"""统一调用插件接口"""
if plugin_name not in plugin_registry:
return f"插件 {plugin_name} 不存在"
plugin_func = plugin_registry.get(plugin_name)
return plugin_func(*args, **kwargs)
# 业务使用
print(run_plugin("text_upper", "hello python"))
print(run_plugin("num_count", [10, 20, 30, 40]))
print(run_plugin("time_format", 1735689600))
代码说明:
- 主程序只定义注册中心与调用接口,新增插件只需添加注册函数,无需改动主逻辑;
- 统一调用入口降低业务代码耦合,适合小型工具、脚本项目快速扩展;
- catalogue 无依赖特性,可直接嵌入脚本,无需复杂环境配置。
运行结果:
HELLO PYTHON
{'sum': 100, 'max': 40, 'min': 10}
2024-01-01 00:00:00
4.2 命令行工具命令注册
结合 catalogue 可快速实现轻量级命令行工具,替代复杂框架,适合个人脚本与自动化工具。
# 命令注册器
cmd_registry = catalogue.create("cli", "commands")
# 注册命令
@cmd_registry.register("start", desc="启动服务")
def start_service():
print("服务启动成功")
@cmd_registry.register("stop", desc="停止服务")
def stop_service():
print("服务已停止")
@cmd_registry.register("status", desc="查看服务状态")
def check_status():
print("服务运行正常")
# 模拟命令行执行
import sys
def cli_main():
if len(sys.argv) < 2:
print("可用命令:")
for cmd, meta in cmd_registry.items_meta():
print(f" {cmd}: {meta.get('desc', '无描述')}")
return
cmd = sys.argv[1]
run_plugin(cmd)
# 直接测试
if __name__ == "__main__":
# 模拟执行命令 python script.py start
run_plugin("start")
run_plugin("status")
代码说明:
- 命令行工具通过注册器管理所有命令,新增命令只需添加装饰器;
- 可自动生成帮助信息,减少重复代码;
- 适合快速开发运维脚本、自动化工具。
五、catalogue 与同类库对比
相比 pluggy、stevedore 等专业插件库,catalogue 优势在于极致轻量、零依赖、使用简单,无需学习复杂概念,适合小型项目、脚本、快速原型开发;而专业插件库适合大型项目的动态加载、多文件插件管理。
在日常脚本、小型工具、教学项目中,catalogue 足以满足对象注册、插件管理、命令绑定等需求,且不会增加项目体积,是 Python 轻量化开发的优质选择。
相关资源
- Pypi地址:https://pypi.org/project/catalogue/
- Github地址:https://github.com/explosion/catalogue
- 官方文档地址:https://catalogue.readthedocs.io/
关注我,每天分享一个实用的Python自动化工具。
