Search code examples
pythonpython-imaging-librarykeyerror

Trying to understand a KeyError


I have a code which compares image files in order to check if images in one directory match with any of the images in an other directory. I am not comparing file names, I am using PIL, the Python Imaging Library to actually compare the images.

My code returns a list with directory names that did not have a match, which is what I need. I have a 162 directories with images. My code checked 71 directories successfully and returned the desired output as expected. Then, starting at directory 72 I get the following: KeyError: 'F:/162 pic sets ready/set72' for all the rest of the directories.

This is the part I can not understand: if I move these directories to an other location, I still get the same error but if I copy the images from these directories into an other, empty directory and run the code on those directories I don't get the error.

from PIL import ImageChops
from PIL import Image
import math, operator
import os

path_images = ('C:/Users/Acer/Desktop/pics/')
list_to_match = []
for images in os.listdir(path_images):
    images_to_match = Image.open(path_images + images)
    list_to_match.append(images_to_match)
path_folders = ('F:/162 pic sets ready/')
d = {}
for dirpath, dirnames, filenames in os.walk(path_folders):
    if 'Thumbs.db' not in filenames:
        d[dirpath] = filenames
dict2 = {k: list(map(lambda x: (k+'/'+x ), v)) for k,v in d.items()}

c = 1
matches = []
folder_images_opened = []
while (c < 163):
    for im in dict2['F:/162 pic sets ready/set%s' % c]:
        test = Image.open(im)
        folder_images_opened.append(test)
    for images_to_find in list_to_match:
        if images_to_find in folder_images_opened:
            matches.append(c)
            print ('Folders where we found a match:', c)
            del folder_images_opened[:]    
    c = c+1
numbers = list(range(1,163))
numbers_filter = [i for i in numbers if i not in matches]
print ('Folders that does not have a match', numbers_filter)

This is the full Traceback:

KeyError                                  Traceback (most recent call last)
<ipython-input-8-c663c9d71cf9> in <module>()
      4 
      5 while (c < 80):
----> 6     for im in dict2['F:/162 pic sets ready/set%s' % c]:
      7         test = Image.open(im)
      8         folder_images_opened.append(test)

KeyError: 'F:/162 pic sets ready/set72'

Solution

  • You are making two assumptions:

    1. That the directory F:/162 pic sets ready/set72 actually exists, and
    2. That if it exists, there is no Thumbs.db filename in that directory.

    If either assumption doesn't hold, then that path doesn't appear as a key in dict2.

    You could simply test if the key exists first:

    while (c < 163):
        dirname = 'F:/162 pic sets ready/set%s' % c
        if dirname not in dict2:
            print('{} does not exist or has a Thumbs.db file'.format(dirname))
            continue
        for im in dict2[dirname]:
            test = Image.open(im)
    

    Rather than use a while loop and expect all setx directories to exist in sequence, loop over the keys of dict2; you could sort the keys even:

    for dirname in sorted(dict2):
        directoryname = os.path.basename(dirname)  # 'set<somenumber>'
    

    I think you just wanted to *skip Thumbs.db, not skip directories containing Thumbs.db (a big difference!). If so, test for the filename when processing the files, not when processing the directories:

    for im in dict2['F:/162 pic sets ready/set%s' % c]:
        if os.path.basename(im) == 'Thumbs.db':
            continue
        test = Image.open(im)
        folder_images_opened.append(test)
    

    and remove the if 'Thumbs.db' not in filenames: test altogether.