Funboost 故障排查

SkillCommunication

Use when encountering errors with funboost, abnormal consumption, process exits, and similar issues. Trigger scenarios: consumers not starting, messages not being consumed, processes hanging, event loop errors, logs not outputting, PYTHONPATH problems, Ctrl+C not exiting. Keywords: troubleshooting,

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Funboost 故障排查 skill

What this skill tells your AI

The instructions your AI receives, as published by ydf0509/funboost in .agents/skills/funboost-troubleshooting/SKILL.md and read by ahel’s review.

概述

本 skill 面向用户和 AI agent,在 funboost 运行异常时按症状快速定位原因。

排查原则:

  1. 先确认 PYTHONPATHfunboost_config.py 是否被正确加载
  2. 再核对 queue_name / broker_kind / 连接配置 是否发布端与消费端一致
  3. 最后看日志(控制台 + 文件)中的连接错误、参数校验错误、重试信息

1. Windows 下 Ctrl+C 为什么无法退出程序

consume() 启动非守护线程(daemon=False),Windows 的 Ctrl+C 无法中断非守护线程。解决:

from funboost import enable_ctrl_c_quit_on_windows

my_task.consume()
enable_ctrl_c_quit_on_windows()  # 让 Ctrl+C 能停止进程;不加也能消费,只是得关窗口或 kill

AI 测试脚本用 time.sleep(N); os._exit(66) 自动退出。


2. PYTHONPATH 和配置文件找不到

2.1 为什么必须设置

funboost 通过 importlib.import_module('funboost_config') 读取配置(见 funboost/set_frame_config.py)。框架不限制项目目录结构,脚本可在任意深层目录运行,因此需要把funboost_config.py 的目录加入 sys.path

2.2 设置方式

# PowerShell
$env:PYTHONPATH="D:\codes\myproj"

# CMD
set PYTHONPATH=D:\codes\myproj & python dir2\dir3\run.py

# Linux / macOS
export PYTHONPATH=/home/user/myproj/; python3 dir2/dir3/run.py

多环境 / 多项目共享配置:

export PYTHONPATH=/data/config_prod/:/data/app/myproject/

PYTHONPATH 中靠前的路径优先被 import funboost_config 命中。

2.3 配置加载优先级

  1. 启动脚本所在目录的 funboost_config.pysys.path[0]
  2. 项目根目录(sys.path[1])的 funboost_config.py
  3. 任意在 PYTHONPATH 中的目录

首次找不到时,框架会在 sys.path[1](通常是项目根目录)自动生成配置模板。

2.4 常见错误

错误处理
ModuleNotFoundError: funboost_config设置 PYTHONPATH 指向项目根,或在项目根目录下运行脚本

何时需要设 PYTHONPATH:只有当你从深层子目录或项目外部目录运行脚本时才需要。如果 cwd 就是项目根目录(含 funboost_config.py),Python 自动把 cwd 加入 sys.path,无需额外设置。funboost 允许脚本放在任意位置运行,这是它的灵活性所在。


3. 消费者不消费

确认写了 my_task.consume() 即可。


4. Event loop 报错

4.1 RuntimeError: This event loop is already running

典型场景: 使用 ConcurrentModeEnum.ASYNC + specify_async_loop=loop,同时在主线程又调用 loop.run_forever(),而 funboost 子线程已通过 is_auto_start_specify_async_loop_in_child_thread=True(默认)启动了同一个 loop。

解决:

@boost(BoosterParams(
    queue_name='my_async',
    concurrent_mode=ConcurrentModeEnum.ASYNC,
    specify_async_loop=loop,
    is_auto_start_specify_async_loop_in_child_thread=False,  # 禁止 funboost 自动启动 loop
))
async def my_task(x): ...

# 主线程自己启动 loop(仅当业务代码也需要同一 loop 时)
loop.run_forever()

或:不要在主线程再 run_forever(),让 funboost 自动管理 loop。

4.2 attached to a different loop / aiohttp 连接池报错

ASYNC 模式在子线程的 loop 中运行协程。若连接池(aiohttp、aiomysql 等)在主线程 loop 创建,子线程无法使用。

解决:传递 specify_async_loop

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
ss = aiohttp.ClientSession(loop=loop)

@boost(BoosterParams(
    queue_name='test_async',
    concurrent_mode=ConcurrentModeEnum.ASYNC,
    specify_async_loop=loop,
))
async def async_task(x):
    async with ss.request('get', url=url) as resp:
        ...

不需要 specify_async_loop 的情况: 函数内临时创建请求(如 async with aiohttp.request(...)),不用全局连接池。

httpx、sqlalchemy 等 通常无此问题。

4.3 在 FastAPI / 已有 event loop 中阻塞

禁止在 async 路由里用同步 AsyncResult.result——会阻塞整个 event loop。异步环境用 AioAsyncResult + await

4.4 ASYNC 模式内写同步阻塞代码

concurrent_mode=ASYNC 时,函数内不能出现 requests.gettime.sleep 等同步阻塞,否则卡死整个 loop。IO 密集型可改用默认 THREADING 模式。


5. 日志不输出 / 找不到日志文件

5.1 日志位置

  • 控制台: 框架启动即有输出(含 funboost 标志、配置提示)
  • 文件: 由项目根目录 nb_log_config.pyLOG_PATH 决定(默认常为 ~/pythonlogsD:/pythonlogs
  • 消费者启动时会打印:队列 xxx 的日志写入到 {LOG_PATH} 文件夹的 {log_filename} ...

5.2 BoosterParams 日志相关字段

字段说明
log_level=10默认 DEBUG。99.999% 的情况下保持 DEBUG 即可——funboost 的 publisher/consumer 日志使用独立的 logger 命名空间,不会影响其他模块的日志级别
create_logger_file=False仅控制台,不写文件
log_filename=None默认用 funboost.{queue_name}.log

5.4 AI agent 捕获输出(推荐)

脚本最开头设置环境变量(参考 funboost/md_for_ai/for_ai_run_demo.py):

import os
os.environ["LOG_PATH"] = r"D:/pythonlogs/ai_console_outs"
os.environ["PRINT_WRTIE_FILE_NAME"] = "my_test_run_20260630_1"  # 每次唯一后缀
os.environ["SYS_STD_FILE_NAME"] = "my_test_std_20260630_1"

运行后读取 LOG_PATH 下带日期前缀的文件,如 2026-06-30.0001.my_test_run_20260630_1.print

5.5 排查清单

  • create_logger_file 是否为 True
  • LOG_PATH 目录是否存在、有写权限
  • 是否把 log_level 设太高导致看不到 DEBUG
  • 多进程消费时,各进程写同一日志文件(正常)

6. 安装依赖冲突

6.1 总体原则(FAQ 10.0)

funboost 固定了部分依赖版本,但用户可自由选择三方包版本。建议 requirements.txt 第一行写 funboost,后面写项目依赖,让 pip 用你指定的版本覆盖。小版本差异通常无问题;报错再针对性降级/升级。

6.2 pydantic

funboost 40.0+ 使用 BoosterParams(Pydantic 模型)。臆造字段会 ValidationError——查 md_for_ai 确认字段名(如 function_timeout 不是 timeout)。

IDE 补全:PyCharm 安装 pydantic 插件;高版本 PyCharm 已内置支持。

6.3 pywin32(仅 Windows)

ImportError: DLL load failed while importing win32file

到 Python 安装目录的 Scripts 下执行:

python.exe pywin32_postinstall.py -install

(用当前环境对应的 python.exe

6.5 SQLite 队列 read-only(Linux/macOS)

默认 SQLLITE_QUEUES_PATH='/sqllite_queues' 无写权限。在 funboost_config.py 改为有权限的路径:

class BrokerConnConfig(DataClassBase):
    SQLLITE_QUEUES_PATH = '/home/user/myproj/sqlite_queues'

7. AI agent 运行 funboost 脚本注意事项

7.1 必须设置 PYTHONPATH

$env:PYTHONPATH="D:\codes\funboost"   # 项目根目录

在命令行设置,不要假设脚本内设置一定生效(import funboost 时配置已加载)。

7.2 消费脚本不会自动退出

consume() 后进程永久运行。禁止直接 python script.py 不设超时。

方式 A — subprocess + timeout(脚本无需 os._exit):

import subprocess, os
subprocess.run(
    ['python', 'tests/ai_codes/my_test.py'],
    cwd=r'D:\codes\funboost',
    timeout=30,  # 一般 >10s,最大不超过 50s
    env={**os.environ, 'PYTHONPATH': r'D:\codes\funboost'},
)

⚠️ 不要用 cmd /c "timeout /t 30 & python script.py"——那是先空等再启动,不能限制 python 运行时长。

方式 B — 脚本内 os._exit(推荐,配合日志文件):

os.environ["LOG_PATH"] = r"D:\pythonlogs\ai_console_outs"
os.environ["PRINT_WRTIE_FILE_NAME"] = f"test_{unique_id}"
os.environ["SYS_STD_FILE_NAME"] = f"test_std_{unique_id}"
# ... push + consume ...
time.sleep(estimated_seconds)
os._exit(66)

然后读取 LOG_PATH 下输出文件验证。

7.3 超时 / sleep 时间估算

  • 框架启动:5–10 秒
  • 默认 concurrent_num=50qps=None
  • 无 qps:吞吐量 ≈ concurrent_num / 函数耗时
  • 有 qps:吞吐量 ≈ min(qps, concurrent_num / 函数耗时)
  • 合理时间 ≈ 启动(5-10s) + 消息数/吞吐量 + 缓冲(2-5s)

7.4 禁止行为

  • 禁止 flush Redis(不要清空用户数据)
  • 不要用 threading.Thread 包装 consume()
  • 不要臆造 BoosterParams 字段名

8. 常见错误信息 → 解决方案对照表

错误信息 / 症状原因解决方案
Ctrl+C 无反应(Windows)非守护线程阻止进程退出如果想用 Ctrl+C 结束程序,加 enable_ctrl_c_quit_on_windows()
ModuleNotFoundError: funboost_config未设 PYTHONPATH / 无配置文件设置 PYTHONPATH;首次运行自动生成模板
Redis 连 localhost 失败未加载用户 funboost_config检查 PYTHONPATH 与配置路径
消息 push 成功但不执行queue_name 不一致发布/消费 queue_name 完全相同
消息 push 成功但不执行未调用 consume()启动消费者
消息 push 成功但不执行broker_kind 不一致统一 broker_kind 与连接配置
TypeError: ... unexpected keyword argument消息字段与函数参数不匹配对齐参数名;或用 **kwargs + should_check_publish_func_params=False
ValidationError(BoosterParams)臆造或拼错字段名BoosterParams 官方字段(如 max_retry_times
RuntimeError: This event loop is already running同一 loop 被 funboost 与主线程重复 run_foreveris_auto_start_specify_async_loop_in_child_thread=False 或去掉主线程 run_forever
attached to a different loop / aiohttp 超时上下文错误连接池 loop 与消费 loop 不一致specify_async_loop=主线程loop
ImportError: DLL load failed ... win32filepywin32 未正确安装运行 pywin32_postinstall.py -install
read-only file system ... /sqllite_queuesSQLite 路径无写权限修改 SQLLITE_QUEUES_PATH
日志「掉线或关闭消费者」「重新放入未确认任务」ACK broker 重启后的正常行为无需处理;不需 ACK 则用 BrokerEnum.REDIS
AsyncResult.result 在 async 环境卡死阻塞 event loopAioAsyncResult + await
进程「卡死」不退出consume 永久循环预期行为;测试用 timeout 或 os._exit
找不到日志文件LOG_PATH 或 create_logger_file查启动日志中的路径;设 LOG_PATH 环境变量
funboost 30.0 配置升级报错旧版 flat 配置删除旧配置,用 BrokerConnConfig
RPC 无返回值未开 RPC 模式is_using_rpc_mode=True 且配置 Redis

快速决策树

遇到问题
├─ 配置文件找不到?
│   └─ 从项目根目录运行,或设 PYTHONPATH
├─ 消费者不消费?
│   └─ 确认调了 consume()
├─ Windows Ctrl+C 停不掉?
│   └─ 加 enable_ctrl_c_quit_on_windows()
├─ asyncio 报错?
│   └─ specify_async_loop | 勿重复 run_forever | 勿在 ASYNC 里写同步阻塞
└─ 安装/依赖报错?
    └─ pywin32_postinstall | pydantic 字段 | requirements 第一行 funboost

参考文档

  • FAQ:funboost_docs/source/articles/c6.md(6.18 PYTHONPATH、6.25 Ctrl+C、6.26 ASYNC、6.28 ACK 提示)
  • 安装兼容:funboost_docs/source/articles/c10.md(pywin32、APScheduler、SQLite read-only)
  • 配置加载:funboost/set_frame_config.py
  • Ctrl+C 实现:funboost/utils/ctrl_c_end.py
  • AI 运行规范:AGENTS.md 第十二节
  • 测试 skill:.agents/skills/developing-funboost-testing/SKILL.md

相关 Skill

  • developing-funboost-testing — 编写与运行测试
  • funboost-async-programming — async/await 异步编程

Signals

GitHub stars
891
Forks
166
Last commit
Aug 2026
Advanced
Catalog kind
skill
Gateway key
funboost-troubleshooting
Source
github.com/ydf0509/funboost