I'm trying to make a list of all png files in a folder that contains other folders. Here's my code.
import os
filelist=os.listdir('images')
for fichier in filelist:
if not(fichier.endswith(".png")):
filelist.remove(fichier)
print(filelist)
problem is, that last print shows that some of the subfolders (but not all) escaped the culling...
['aa.png', 'Nouveau dossier - Copie', 'Nouveau dossier - Copie (3)', 'Nouveau dossier - Copie (5)', 'zz.png']
What am I doing wrong ?
Summary: Never, ever, ever modify the list that you are iterating over.
Instead, iterate over a copy:
import os
filelist=os.listdir('images')
for fichier in filelist[:]: # filelist[:] makes a copy of filelist.
if not(fichier.endswith(".png")):
filelist.remove(fichier)
print(filelist)
Or if you don't like to make unnecessary copies, iterate in reverse (this will only work if you can guarantee that the items in the list are unique; for a file system this is a good assumption):
for fichier in reversed(filelist):
# do stuff
Note that you can use Python's glob
module to simplify this:
import glob
print(glob.glob('images/*.png'))
When you iterate over a list in Python, behind the scenes Python is actually iterating over the indices of the list. You can see that this is a huge problem whenever you actually remove the items:
l = [1, 2, 2, 3]:
for x in l:
if x%2 == 0:
l.remove(x)
print('x == {}'.format(x))
print('l == {}'.format(l))
You can tell by what is printed here that the second 2 is skipped, and that l
has a value of [1, 2, 3]
. This is because, whenever the first 2 is reached and removed, the index is 1
(the second element). On the next iteration, the index is 2
. At this point, l == [1,2,3]
, so x == 3
. If you run the code, it will probably be more obvious than this explanation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With