这个问题之前遇到过,但是忘了上次怎么解决的了。。。
1、问题描述:
对训练好的模型进行测试,正常结果是得到mAP然后生成json文件保存检测框,错误出在保存检测结果上。
错误堆栈信息:
Traceback (most recent call last):
File "tools/train.py", line 198, in <module>
main()
File "tools/train.py", line 187, in main
train_detector(
File "/data/lxy1/pointobb-main/PointOBB/mmdet/apis/train.py", line 179, in train_detector
runner.run(data_loaders, cfg.workflow) #开始训练
File "/data/lxy1/Anaconda3/envs/openmmlab/lib/python3.8/site-packages/mmcv/runner/epoch_based_runner.py", line 117, in run
self.call_hook('before_run')
File "/data/lxy1/Anaconda3/envs/openmmlab/lib/python3.8/site-packages/mmcv/runner/base_runner.py", line 317, in call_hook
getattr(hook, fn_name)(self)
File "/data/lxy1/pointobb-main/PointOBB/mmdet/core/evaluation/eval_hooks.py", line 24, in before_run
self._do_evaluate(runner)
File "/data/lxy1/pointobb-main/PointOBB/mmdet/core/evaluation/eval_hooks.py", line 48, in _do_evaluate
key_score = self.evaluate(runner, results)
File "/data/lxy1/Anaconda3/envs/openmmlab/lib/python3.8/site-packages/mmcv/runner/hooks/evaluation.py", line 367, in evaluate
eval_res = self.dataloader.dataset.evaluate(
File "/data/lxy1/pointobb-main/PointOBB/mmdet/datasets/cocofmt_obb.py", line 480, in evaluate
shutil.copy(result_files[metric], save_result_file)
File "/data/lxy1/Anaconda3/envs/openmmlab/lib/python3.8/shutil.py", line 417, in copy
if os.path.isdir(dst):
File "/data/lxy1/Anaconda3/envs/openmmlab/lib/python3.8/genericpath.py", line 42, in isdir
st = os.stat(s)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not list
2、猜想一
报错 TypeError: stat: path should be string, bytes, os.PathLike or integer, not list
通常是由于在某个文件操作中传递了一个列表,而不是期望的路径字符串。这个错误可能出现在以下几种情况下:
- 文件路径参数传递错误:某个函数期望传入文件路径作为参数,但传入了一个列表。
- 配置文件路径解析错误:在解析配置文件路径时,路径格式不正确。
根据提供的错误信息,问题出现在 shutil.copy(result_files[metric], save_result_file)
这一行代码。错误提示显示 os.stat
接收到一个列表,而不是字符串、字节、os.PathLike
对象或整数。这意味着 result_files[metric]
或 save_result_file
是一个列表,而不是期望的路径字符串。debug一下:
try:
print(f"result_files[metric]: {result_files[metric]}, type: {type(result_files[metric])}") # /tmp/tmpyfqlpycg/results.bbox.json, type: <class 'str'>
print(f"save_result_file: {save_result_file}, type: {type(save_result_file)}") #['xxx/work_dir/test_pointobb_r50_fpn_2x_dior/pseudo_obb_result.json'], type: <class 'list'>
import shutil
save_result_file = './exp/latest_result.json' if save_result_file is None else save_result_file
shutil.copy(result_files[metric], save_result_file)
except IndexError:
print_log(
'The testing results of the whole dataset is empty.',
logger=logger,
level=logging.ERROR)
break
结果显示save_result_file是一个列表,它的元素是传入的字符串,代表结果文件存储路径。不知道为什么会变成列表,对于这种复杂又庞大的程序,有时候追究原因会耗费大量的时间,所以直接在能看到的问题的基础上解决比较省力。修改后的代码:
try:
print(f"result_files[metric]: {result_files[metric]}, type: {type(result_files[metric])}") # /tmp/tmpyfqlpycg/results.bbox.json, type: <class 'str'>
print(f"save_result_file: {save_result_file}, type: {type(save_result_file)}") #['xxx/work_dir/test_pointobb_r50_fpn_2x_dior/pseudo_obb_result.json'], type: <class 'list'>
import shutil
save_result_file = './exp/latest_result.json' if save_result_file is None else save_result_file
# 如果 save_result_file 是列表,取第一个元素作为文件路径
if isinstance(save_result_file, list):
save_result_file = save_result_file[0]
print(f"Using first element of save_result_file: {save_result_file}")
# 确保 save_result_file 是字符串
if not isinstance(save_result_file, str):
raise TypeError(f"save_result_file is {type(save_result_file)}, expected a string")
shutil.copy(result_files[metric], save_result_file)
成功保存文件