TypeError:NoneType - 使用return zip_longest时

时间:2015-08-19 22:30:41

标签: python windows typeerror nonetype

我现在收到NoneType的类型错误(我假设当我尝试在zip_longest函数中返回一个值时)

我的代码的目标是删除小于“width = 400 AND height = 400”的图像文件,然后将所有剩余的图像放入x值的文件夹中(其中x可以在以后更改)。目前代码似乎工作,但我得到了我提到的问题,并希望防止该错误。

代码:

# ======== grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx:
def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    print(fillvalue)
    return zip_longest(*args, fillvalue=fillvalue)


def makedirs(d):
    try:
        os.makedirs(d)
    except OSError as e:
        # If the file already exists, and is a directory
        if e.errno == errno.EEXIST and os.path.isdir(d):
            created = False
        # It's some other error, or the existing file is not a directory
        else:
            raise
    else:
        created = True

    return created


def get_valid_filenames(directory, extensions):
    for filename in os.listdir(directory):
        if filename.lower().endswith(extensions):
            yield filename


def get_too_small_image_filenames(directory, extensions=DEFAULT_IMAGE_EXTS,
                                  min_width=400, min_height=400):
    for filename in get_valid_filenames(directory, extensions):
        image_path = os.path.join(directory, filename)
        try:
            with open(image_path, 'rb') as filehandle:
                img = Image.open(filehandle)
                width, height = img.size
        except IOError, e:
                yield filename

        if (width < min_width) and (height < min_height):
            yield filename


def confirm_it(directory, extensions, images_per_dir=500):
    # Confirm selection and move files to new sub-directory

        for too_small_filename in get_too_small_image_filenames(directory):
            os.remove(os.path.join(directory, too_small_filename))

        valid_images = get_valid_filenames(directory, extensions)
        grouped_image_file_names = grouper(valid_images, images_per_dir)
        for subdir, image_filenames in enumerate(grouped_image_file_names):
            for filename in image_filenames:
                from_path = os.path.join(directory, filename)

                to_dir = os.path.join(directory, "Folder ("+str(subdir)+")")
                to_path = os.path.join(to_dir, filename)

                makedirs(to_dir)
                os.rename(from_path, to_path)


def confirm_it_wrapper():
    confirm_it(directory=folderPath.get(), extensions=extensions)

回溯:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1486, in __call__
    return self.func(*args)
  File "C:\Users\Gavin\workspace\Test Projects\src\Test0.py", line 109, in confirm_it_wrapper
    confirm_it(directory=folderPath.get(), extensions=extensions)
  File "C:\Users\Gavin\workspace\Test Projects\src\Test0.py", line 99, in confirm_it
    from_path = os.path.join(directory, filename)
  File "C:\Python27\lib\ntpath.py", line 66, in join
    p_drive, p_path = splitdrive(p)
  File "C:\Python27\lib\ntpath.py", line 114, in splitdrive
    if len(p) > 1:
TypeError: object of type 'NoneType' has no len()

额外信息:

如前所述,我相信它来自一个返回“zip_longest”参数的函数,其中fillvalue在创建中设置为“None”。有什么方法吗?

感谢。

1 个答案:

答案 0 :(得分:1)

问题是文件数量不是images_per_dir的倍数,因此最后一组images_per_dir图片会填充None个。{将此trim_grouper()函数添加到您的代码中以处理该问题:

from itertools import takewhile

def trim_grouper(iterable, n, fillvalue=None):
    for group in grouper(iterable, n, fillvalue=fillvalue):
        yield tuple(takewhile((lambda x: x), group))

然后在confirm_it()中,替换:

grouped_image_file_names = grouper(valid_images, images_per_dir)

使用:

grouped_image_file_names = trim_grouper(valid_images, images_per_dir)

应该这样做。