运行Tiny ImageNet构建脚本报NoneType不可迭代错误修复方法
报错现象
运行脚本时抛出如下异常:
File "/home/user/tiny_imagenet/make_tiny_imagenet.py", line 238, in
wnids = [line.strip() for line in args.wnid_file]
TypeError: 'NoneType' object is not iterable
问题根因
- 参数定义缺失必填约束:使用
argparse注册--wnid_file参数时,既没有设置required=True标记为必填项,也没有配置默认值,运行脚本时未传入该参数的情况下,args.wnid_file会被自动赋值为None - 无效迭代触发异常:第238行的列表推导式直接尝试遍历
args.wnid_file,而Python中None属于不可迭代对象,遍历操作直接触发类型错误 - 额外隐藏bug:代码开头配置的
train_anns_path、val_anns_path指向的是CSV文件路径,但后续代码多次调用os.listdir()读取这两个路径,该函数仅支持传入目录路径,就算解决了参数问题,这里也会抛出不是目录的错误;另外代码是Python2版本写法,直接在Python3环境运行还会遇到字典方法、切片索引类型的兼容问题。
修复方案
两种方案可按需选择:
方案1:不改代码,运行时传入所有必填参数
提前准备好wnid清单文件(每行写一个需要提取的ImageNet类别wnid,比如Tiny ImageNet官方使用的200个类别wnid列表),运行脚本时把--wnid_file和必填的--out_dir参数一起传入即可,示例命令:
python make_tiny_imagenet.py --wnid_file ./tiny-imagenet-wnids.txt --out_dir ./restored_tiny_imagenet
注意:用这个方案需要提前把代码开头的train_anns_path、val_anns_path改成实际存放ILSVRC标注XML文件的目录路径,不能用原来的CSV文件路径。
方案2:修改代码补全校验和兼容问题,从根源避免报错
- 修正路径配置,把标注路径改成实际的XML标注目录:
# 修正为实际存放ILSVRC训练/验证集标注XML的目录 train_anns_path = '/home/user/tiny_imagenet/ILSVRC2012_bbox_train' val_anns_path = '/home/user/tiny_imagenet/ILSVRC2012_bbox_val' train_image_dir = '/data/imagenet/Data/CLS-LOC/train' val_image_dir = '/data/imagenet/Data/CLS-LOC/val'
- 修改argparse参数定义,将必填参数标记为required,避免漏传:
parser = argparse.ArgumentParser() parser.add_argument('--wnid_file', type=argparse.FileType('r'), required=True, help='存储wnid列表的文本文件,每行一个wnid') parser.add_argument('--num_train', type=int, default=100) parser.add_argument('--num_val', type=int, default=100) parser.add_argument('--image_size', type=int, default=64) parser.add_argument('--out_dir', required=True, help='生成数据集的输出目录') args = parser.parse_args()
- 修复Python3兼容问题:
- 把代码中两处
.iteritems()替换为.items(),适配Python3字典接口 - 把中心裁剪逻辑里的
h0 = (h - w) / 2、w0 = (w - h) / 2中的除法改成整数除法//,避免浮点数作为数组切片索引报错
改完之后再用方案1的命令运行即可,不会再触发参数相关的报错。
- 把代码中两处
内容的提问来源于stack exchange,提问作者dtr43
相关产品推荐
相关产品推荐

