如何在FreeSWITCH的mod_python3中避免缓存问题?
解决FreeSWITCH mod_python3模块缓存导致修改后需重启的问题
问题场景
在基于FreeSWITCH开发Python应用时,通过mod_python3在拨号计划中调用脚本,脚本依赖的自定义模块修改后,必须重启FreeSWITCH才能生效。核心原因是mod_python3在FS运行期间会维持一个持久的Python环境,首次加载的模块会一直驻留内存,无法自动更新。
已尝试的无效方案
- 重载mod_python3模块:在fs_cli执行
reload mod_python3,但模块被标记为不可卸载,执行结果如下:freeswitch@freeswitch> reload mod_python3 +OK Reloading XML -ERR unloading module [Module is not unloadable] -ERR loading module [Module already loaded] - 使用
importlib.reload():在脚本开头显式重载模块,但无法清除FS内存中已加载的缓存:import demoPy.module as module import importlib importlib.reload(module) - 清理本地缓存文件:用
pyclean清理项目下的.pyc等缓存文件,仅清除磁盘缓存,不影响FS内存中的模块实例。
可行解决方案
1. 动态导入+强制重载(开发环境优先)
将模块导入逻辑放到每次调用的入口函数内部,每次触发脚本时都重新导入并重载模块:
def handler(session, args): import importlib # 动态导入目标模块 module = importlib.import_module("demoPy.module") # 强制重载模块 importlib.reload(module) # 调用模块中的业务逻辑 module.process_call(session)
注意:该方案会增加每次调用的性能开销,仅适合开发测试阶段使用,生产环境不建议。
2. 子进程执行独立脚本
把业务逻辑封装到独立的Python脚本中,在mod_python3的入口脚本里通过subprocess启动子进程执行,每次调用都是全新的Python环境,自然避免缓存问题:
import subprocess import sys def handler(session, args): # 传递必要的会话参数给外部脚本 caller_id = session.getVariable("caller_id_number") # 执行外部脚本并捕获输出 proc = subprocess.run( [sys.executable, "/opt/fs_scripts/your_biz_logic.py", caller_id], capture_output=True, text=True ) # 根据脚本输出处理会话 if proc.returncode == 0: session.execute("speak", proc.stdout) else: session.execute("log", f"ERR: {proc.stderr}")
优点:完全隔离缓存,开发测试便捷;缺点:子进程创建有一定性能损耗,生产环境需评估并发量是否可接受。
3. 开发环境用临时FS实例
在开发阶段,避免使用长期运行的FS进程,每次修改模块后启动临时实例测试:
# 启动临时FreeSWITCH实例,指定开发配置 freeswitch -nc -f /etc/freeswitch/dev/freeswitch.xml # 测试完成后终止进程 pkill freeswitch
可以把上述命令封装成shell脚本,一键完成重启测试,效率也很高。
4. 定制mod_python3加载逻辑(进阶)
如果具备C/C++开发能力,可以修改mod_python3的源码:
- 在每次脚本调用前,清理
sys.modules中对应自定义模块的条目,强制重新加载 - 利用Python的子解释器(subinterpreters)特性,为每个脚本调用创建独立的解释器环境,避免模块跨调用缓存
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

