使用pytest+Selenium+Jpype时偶发'fatal Python error: Bus error'问题求助
解决pytest+Selenium+Jpype偶发'fatal Python error: Bus error'问题
问题背景
测试脚本基于pytest和Selenium,偶发出现fatal Python error: Bus error,错误触发在conftest.py的fin函数中,涉及Extent报告的flush()和Jpype的shutdownJVM()操作。未使用套接字、线程等需要手动内存管理的功能,用mprof排查内存泄漏未复现问题,偶发特性导致定位困难。
相关代码:
@pytest.fixture(scope="session") def report_util(request): timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") extent = ExtentReports() if not os.path.exists("../reports/"): os.makedirs("../reports/") extent_reporter = ExtentSparkReporter(f'../reports/report_{timestamp}.html') extent_reporter.config().thumbnailForBase64(True) extent_reporter.config().setCss("img {width: 400px;}") extent.attachReporter(extent_reporter) def fin(): try: extent.flush() jp.shutdownJVM() except Exception as e: print(f"Exception during teardown: {e}") raise request.session.addfinalizer(fin) return extent
可能的原因与修复方案
1. 调整JVM关闭时机与资源释放顺序
Bus error通常源于非法内存访问,这里大概率是Jpype关闭JVM时,Extent的Java对象仍被Python引用,导致内存访问冲突。可以通过以下步骤确保资源完全释放:
- 手动删除Extent相关对象的引用
- 强制触发Python垃圾回收
- 短暂延迟等待Java侧资源清理完成后再关闭JVM
修改后的fin函数示例:
def fin(): try: extent.flush() # 手动释放Extent相关Python引用 del extent del extent_reporter # 强制触发垃圾回收,清理未引用的对象 import gc gc.collect() # 短暂延迟,确保Java侧完成资源释放 import time time.sleep(0.5) # 关闭JVM jp.shutdownJVM() except Exception as e: print(f"Exception during teardown: {e}") raise
2. 确保Jpype JVM的初始化与关闭唯一
检查JVM初始化逻辑,确保整个测试会话中JVM只初始化一次,避免重复初始化或提前关闭导致的内存异常。比如将Jpype的初始化逻辑放在同一个session级fixture中,和报告工具绑定。
3. 升级Jpype与ExtentReports版本
旧版本的Jpype和ExtentReports(尤其是Java实现的部分)可能存在跨语言交互的内存bug,尝试升级到最新稳定版:
- 升级Jpype:
pip install --upgrade jpype1 - 确保使用兼容的ExtentReports Python绑定版本
4. 调整pytest finalizer的执行顺序
pytest的finalizer按反向添加顺序执行,如果其他fixture持有Java对象且finalizer执行晚于当前报告fixture,会导致JVM关闭时仍有Java对象活跃。可以:
- 将
report_utilfixture的依赖声明为其他fixture之后,确保先清理其他Java资源 - 手动调整finalizer的添加顺序,优先执行非报告相关的资源清理
内容的提问来源于stack exchange,提问作者Aeraf khan
相关产品推荐
相关产品推荐

