funworker
轻量级线程流水线框架:生产者 -> 队列 -> 处理单元线程池 -> 队列 -> 消费者,各阶段通过队列解耦。
下游只需要继承三个基类、实现一个方法,就能获得一条可优雅启停的多线程流水线:
| 角色 | 基类 | 需要实现 |
|---|---|---|
| 生产者 | BaseProducer |
produce(self) -> Any |
| 处理单元 | BaseProcessor |
process(self, item) -> Any |
| 消费者 | BaseConsumer |
consume(self, item) -> None |
WorkerPool 负责把 BaseProcessor 包装成多线程执行;Pipeline 负责把它们串起来,提供一个 run()
方法统一管理启动/停止——下游不需要接触 producer/consumer 内部的线程细节。
安装
pip install -e .
快速上手
from funworker import BaseConsumer, BaseProcessor, BaseProducer, Pipeline, SKIP
class NumberProducer(BaseProducer):
def __init__(self, *args, total=10, **kwargs):
super().__init__(*args, **kwargs)
self._total = total
self._current = 0
def produce(self):
if self._current >= self._total:
raise StopIteration # 数据生产完毕(有限任务场景)
value = self._current
self._current += 1
return value
class SquareProcessor(BaseProcessor):
def process(self, item):
result = item * item
return (
result if result % 2 == 0 else SKIP
) # SKIP 表示丢弃这条数据;None 是合法业务值
class PrintConsumer(BaseConsumer):
def consume(self, item):
print(f"result = {item}")
pipeline = Pipeline.build(
producer_cls=NumberProducer,
processor=SquareProcessor, # 也可以传实例,或一个返回实例的工厂函数
consumer_cls=PrintConsumer,
num_workers=4,
)
pipeline.run() # 启动并阻塞:生产者自然结束,或收到 SIGINT/SIGTERM 后,自动优雅停止整条流水线
print(pipeline.stats())
不用 run() 阻塞、而是想在流水线运行期间做别的事情(轮询指标等)时,用 with 语法:进入时自动
启动,退出时自动优雅停止排空,全程不需要访问 producer.join()。BaseProducer/BaseConsumer/
WorkerPool/Pipeline 都支持 with。
示例
example/ 目录下有更多可以直接运行的完整示例,其他仓库可以直接参考/复制:
| 示例 | 说明 |
|---|---|
basic_usage.py |
最小可运行示例:run() 与 with 两种用法 |
multi_stage_pipeline.py |
串联多级处理:add_stage() + set_consumer() |
fan_out_fan_in.py |
一拆多 Many(fan-out)+ 多合一 BaseBatchProcessor(fan-in / 批处理) |
retry_dead_letter_queue.py |
失败重试 + 死信队列 |
progress_logging.py |
运行时进度日志:CountingQueue + format_progress()/log_progress() |
特性
run()一步启停:Pipeline.run()内部处理启动顺序、SIGINT/SIGTERM优雅停止、异常传播, 下游不需要手动调用producer.join()。SKIP/None语义分离:produce()/process()返回None是合法的业务数据;返回funworker.SKIP才表示"丢弃这条,不进入下游队列"。- 异常传播:任一线程内部抛出未捕获异常,会被捕获并在
join()/stop()/run()时重新抛出, 不会静默崩溃。 - 失败重试 + 死信队列:
WorkerPool(..., max_retries=3, dead_letter_queue=dlq),处理失败的数据 会重新排队重试,重试耗尽后写入死信队列(不配置则丢弃并记录日志)。见retry_dead_letter_queue.py。 - 监控指标:
producer.stats()/pool.stats()/consumer.stats()/pipeline.stats()返回 已处理/失败/重试计数、队列长度、线程存活状态,方便接入监控。 - 多级流水线:
pipeline.add_stage(processor2, num_workers=2)可以在第一级处理单元后追加更多级, 上一级的输出队列自动作为下一级的输入队列;最后用pipeline.set_consumer(ConsumerCls)挂消费者。见multi_stage_pipeline.py。 - 幂等停止:
stop()/pool.stop()重复调用是安全的,第二次起直接返回。 - 按 CPU 核数自适应:
num_workers不传时默认取os.cpu_count(),多数场景不需要手动调线程数。 - 一拆多(fan-out)/ 多合一(fan-in):
process()返回funworker.Many([...])把一条拆成多条; 继承BaseBatchProcessor实现process_batch(items)把多条合成一批处理,停止时缓冲区剩余数据 也会强制产出,不丢数据。见fan_out_fan_in.py。 - 运行时进度日志:
format_progress()/log_progress()(BaseProducer/WorkerPool/BaseConsumer/Pipeline都有),统一"名字(当前/历史)"三段式,每一段的名字都可以单独设置; 配合funworker.CountingQueue还能看到每条队列的历史累计吞吐量。见progress_logging.py。 with语法:BaseWorker(因此BaseProducer/BaseConsumer)、WorkerPool、Pipeline都实现了__enter__/__exit__,避免忘记调用停止方法导致线程泄漏。
设计要点
- 职责分离:
BaseProcessor完全不感知线程/队列,只关心"一条数据怎么处理",方便单测和复用。 - 每线程独立实例:
WorkerPool默认给每个线程创建独立的BaseProcessor实例(传类或工厂函数即可), 处理单元可以放心持有数据库连接、http session 等非线程安全资源。 - 优雅停止:内部使用
STOP哨兵对象 +Queue.join()drain,保证停止前把队列里已有数据处理完, 不丢数据。 - 错误隔离与可见性:单条数据处理异常默认走
on_error钩子记录日志(并按配置重试/进死信队列), 不会打断整条流水线;但线程自身崩溃(如on_start抛异常)会被显式传播给调用方,不会被吞掉。 - 可扩展:
Pipeline是对BaseProducer+ 一至多级WorkerPool+BaseConsumer的编排,add_stage()/set_consumer()让多级处理流水线的写法和单级一样简单。
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file funworker-0.1.1-py3-none-any.whl.
File metadata
- Download URL: funworker-0.1.1-py3-none-any.whl
- Upload date:
- Size: 21.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
693f811d1c21408ac15056ad0ddfb076124331448659b7c96387064de3be2905
|
|
| MD5 |
4f8e4346b9fa5ac98f0114d08ed9d507
|
|
| BLAKE2b-256 |
34d8b2a554f6c64598bcb64a6ad1b949cb1dd879d3851ec721c99b4d5d695ae0
|