【问题标题】:TypeError: 'NoneType' object is not iterable - but still seems to iterate through the list?TypeError: 'NoneType' object is not iterable - 但似乎仍在遍历列表?
【发布时间】:2020-08-15 17:02:38
【问题描述】:

我对编码很陌生,所以感谢您的帮助,如果这很明显,很抱歉。

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, data = return_yolo_data(jpg_fname, ann_dir=WORKING_DIR+'/data/Annotations/')
      5     for f, d in zip(fs, 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, 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)
   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, filehandle, list of strings, or generator. Got <class 'NoneType'> instead.

如果我使用此代码:

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):
        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, names='class,x,y,w,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), x, y, h, w 
    '''
    # empty lists for dictionary
    fnames, classes = [], []
    x,y,h,w = [],[],[],[]
    for jpg_fname in image_list:
        fs, data = return_yolo_data(jpg_fname, ann_dir=ann_dir)
        for f, d in zip(fs, 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

【问题讨论】:

  • print (f) 的结果是什么?列表、字典、元组或其他东西?
  • 感谢您的回复。 print(f) 给出图像文件名的列表(以及该图像中出现的许多对象的文件名实例,例如,如果图像中有 7 个对象,那么列表中将有该文件名的 7 个实例。 print(d ) 以数组的形式给出每个图像中每个对象的所有数据列表。
  • 从 print(f) 创建的列表与文件名的每个实例一起出现在单独的行上,没有逗号或其他语法(我认为这可能是一个线索??)
  • 您可以尝试添加if not f: fnames.append(f)。这将确保您不会添加空列表。问题可能是您尝试附加一个空列表。
  • 再次感谢您的帮助。您的建议引发了相同的错误消息。还刚刚注意到,虽然 print(f) 打印出文件名列表,但之后仍然显示相同的错误。

标签: python iteration


【解决方案1】:

Got &lt;class 'NoneType'&gt; 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

【讨论】:

    【解决方案2】:
    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 让我走上了解决这部分问题的正确轨道)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-17
      • 2022-12-15
      • 2020-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-08
      相关资源
      最近更新 更多