TypeError:'NoneType'对象不是可迭代的-但似乎仍在列表中迭代?

问题描述

我对编码还很陌生,因此感谢您的帮助,如果很明显,我们对此表示歉意。

full_image_list = glob.glob(WORKING_DIR+'/data/JPEGImages/*.jpg')
fnames,classes = [],[]

for jpg_fname in full_image_list:
    fs,data = return_yolo_data(jpg_fname,ann_dir=WORKING_DIR+'/data/Annotations/')
    for f,d in zip(fs,data):
        fnames.append(f)

上面的代码给出以下错误

> ---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~/.virtualenvs/dl4cv/lib/python3.8/site-packages/numpy/lib/npyio.py in genfromtxt(fname,dtype,comments,delimiter,skip_header,skip_footer,converters,missing_values,filling_values,usecols,names,excludelist,deletechars,replace_space,autostrip,case_sensitive,defaultfmt,unpack,usemask,loose,invalid_raise,max_rows,encoding)
   1753             fid_ctx = contextlib_nullcontext(fid)
-> 1754         fhd = iter(fid)
   1755     except TypeError:

TypeError: 'nonetype' object is not iterable

During handling of the above exception,another exception occurred:

TypeError                                 Traceback (most recent call last)
<ipython-input-187-80766db0462f> in <module>
      2 
      3 for jpg_fname in full_image_list:
----> 4     fs,ann_dir=WORKING_DIR+'/data/Annotations/')
      5     for f,data):
      6         fnames.append(f)

<ipython-input-159-ecbad441c355> in return_yolo_data(jpg_fname,ann_dir)
     19     base_fname = jpg_fname.split('/')[-1] # no path
     20     txt_fname = get_yolo_file(base_fname,dir_=ann_dir)
---> 21     data = np.genfromtxt(txt_fname,names='class,x,y,w,h')
     22     # don't fail if there is only one labeled object in an image
     23     data = np.atleast_1d(data)

~/.virtualenvs/dl4cv/lib/python3.8/site-packages/numpy/lib/npyio.py in genfromtxt(fname,encoding)
   1754         fhd = iter(fid)
   1755     except TypeError:
-> 1756         raise TypeError(
   1757             "fname must be a string,filehandle,list of strings,"
   1758             "or generator. Got %s instead." % type(fname))

TypeError: fname must be a string,or generator. Got <class 'nonetype'> instead.

如果我使用此代码

full_image_list = glob.glob(WORKING_DIR+'/data/JPEGImages/*.jpg')
fnames,data):
        print(f)

然后迭代显示每个文件名称,每个文件显示在单独的行中,并且没有逗号/语法,然后再显示相同的错误

这是get_yolo_file函数和其他要求的代码

def get_yolo_file(fname,dir_=WORKING_DIR+'/data/Annotations/'):
    '''
    takes image filename and returns annotation filename
    e.g. data/JPEGImages/IMG_XXX.jpg
         data/Annotations/IMG_XXX.txt
    '''
    txt_file = fname.replace('.jpg','.txt')
    full_path = '/'.join([dir_,txt_file])
    if os.path.isfile(full_path):
        return full_path
    else:
        print('ERROR')
        return None

def return_yolo_data(jpg_fname,ann_dir=WORKING_DIR+'/data/Annotations/'):
    '''
    Reads annotation file,returns name and data
    '''
    base_fname = jpg_fname.split('/')[-1] # no path
    txt_fname = get_yolo_file(base_fname,dir_=ann_dir)
    data = np.genfromtxt(txt_fname,h')
    # don't fail if there is only one labeled object in an image
    data = np.atleast_1d(data)
    # keep file name associated with each label
    fname_arr = [base_fname]*data.shape[0]
    return fname_arr,data

def str_class(val):
    '''
    Return string label for index. 
    YOLO is zero indexed.
    '''
    if val == 0:
        return 'one'
    elif val == 1:
        return 'two'
    elif val == 2:
        return 'three'
    elif val == 3:
        return 'four'
    elif val == 4:
        return 'five'
    elif val == 5:
        return 'six'

def create_image_dict(image_list,ann_dir=WORKING_DIR+'/data/Annotations/'):
    '''
    For input list of images,return a dictionary with label information.
    dictionary keys: image file,class (string),h,w 
    '''
    # empty lists for dictionary
    fnames,[]
    x,w = [],[],[]
    for jpg_fname in image_list:
        fs,ann_dir=ann_dir)
        for f,data):
            fnames.append(f)
            classes.append(str_class(d['class']))
            x.append(d['x'])
            y.append(d['y'])
            h.append(d['h'])
            w.append(d['w'])
    out_dict = {'filename':fnames,'class':classes,'x':x,'y':y,'h':h,'w':w}
    return out_dict

解决方法

Got <class 'NoneType'> instead.

此错误消息明确指出了问题... os.path.isfile(full_path)返回False,因此get_yolo_file返回None

所以txt_fname == None。正如错误所言,np.genfromtxt的文件路径不能为None

因此,而不是“打印”错误(print('ERROR')),您应该执行以下操作:

class MyException(Exception):
    pass

def get_yolo_file(fname,dir_=WORKING_DIR+'/data/Annotations/'):
    '''
    takes image filename and returns annotation filename
    e.g. data/JPEGImages/IMG_XXX.jpg
         data/Annotations/IMG_XXX.txt
    '''
    txt_file = fname.replace('.jpg','.txt')
    full_path = '/'.join([dir_,txt_file])
    if os.path.isfile(full_path):
        return full_path
    else:
        raise MyException("File path is wrong!")

这将引发一个错误,提示File path is wrong!,并终止程序的执行。


关于os.path.isfile(full_path)返回False的原因,您将必须检查该文件在该位置是否实际存在,并且所创建的路径是否是该文件的实际路径。


有关自定义例外的更多信息,请参见custom exceptions

,
def get_yolo_file(fname,dir_=WORKING_DIR+'/data/Annotations/'):
'''
takes image filename and returns annotation filename
e.g. data/JPEGImages/IMG_XXX.jpg
     data/Annotations/IMG_XXX.txt
'''
txt_file = fname.replace('.jpg','.txt')
full_path = '/'.join([dir_,txt_file])
if os.path.isfile(full_path):
    return full_path
else:
    print('ERROR')
    return None

我将full_path中的“ /”替换为“”。由于错误每次都被抛出,所以我知道所有文件都存在。这解决了这个问题。

然后注意到我缺少一个.txt文件(感谢@Hampus Larrson,让我走上正确的道路来解决这一部分)