I have a folder with images that follow this name scheme:
FEATURED_0.png
FEATURED_1.png
FEATURED_2.png
When I want to load them into a list usable by Pillow I do this:
for filename in glob.glob("FEATURED*.png"):
image = Image.open(filename)
featured_list.append(image)
This works pretty ok, but has a flaw. It loads the images, regardless of their number. I already tried loading FEATURED_0 regardless of what, moving into a list and then checking if the next Image has a greater number 1, but that failed miserably.
So back to my question. Is there a way to load Images into a list in python, but in a specific order?
CodePudding user response:
If you want to start with 0
, load each subsequent number, and stop when you hit a number that's not there, use a while
loop:
num = 0
base = "FEATURED_%d.png"
while os.path.isfile(base % num):
featured_list.append(Image.open(base & num))
num = 1
CodePudding user response:
glob
doesn't have option to sort filenames. os.list()
and os.walk()
also can't sort it.
You have to use list = sorted(list)
for this
for filename in sorted(glob.glob("FEATURED*.png")):
But sorted()
without parameters will put _10
before _2
because it checks char after char and first it compares _
with _
and next 1
with 2
and skip rest.
You may need to use sorted(..., key=your_function)
with your_function
which extracts number from filename and converts to integer
- and sorted
will use only this integer
to compare names.
def number(filename):
return int(filename[9:-4])
data = ['FEATURED_0.png', 'FEATURED_1.png', 'FEATURED_2.png', 'FEATURED_10.png']
print(list(sorted(data))) # `_10` before `_2`
print(list(sorted(data, key=number))) # `_2` before `_10`
Result
# `_10` before `_2`
['FEATURED_0.png', 'FEATURED_1.png', 'FEATURED_10.png', 'FEATURED_2.png']
# `_2` before `_10`
['FEATURED_0.png', 'FEATURED_1.png', 'FEATURED_2.png', 'FEATURED_10.png']
def number(filename):
return int(filename[9:-4])
for filename in sorted(glob.glob("FEATURED*.png"), key=number):
# ... code ...
You may also write it with lambda
sorted( data, key=(lambda x:int(x[9:-4])) )
You can create function which returns something more complex - ie. tuple (extension, number)
- and then first you get all .jpg
(sorted by number) and next all .png
(sorted by number)