列出文件夹中的PNG文件

11

我正在尝试列出包含其他文件夹的文件夹中所有png文件的清单。这是我的代码。

import os
filelist=os.listdir('images')
for fichier in filelist:
    if not(fichier.endswith(".png")):
        filelist.remove(fichier)
print(filelist)
问题在于,最后一次打印显示部分子文件夹(但不是全部)逃避了削减...
['aa.png', 'Nouveau dossier - Copie', 'Nouveau dossier - Copie (3)', 'Nouveau dossier - Copie (5)', 'zz.png']

我做错了什么?


你可以使用glob来搜索文件。https://docs.python.org/2/library/glob.html - Håken Lid
2个回答

23

概述: 永远不要修改您正在遍历的列表。

相反,对副本进行迭代:

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)

如果您不想制作无必要的副本,可以进行反向迭代(只有在您可以保证列表中的项是唯一的情况下才能使用此方法;对于文件系统而言,这是一个很好的假设):

for fichier in reversed(filelist):
    # do stuff

请注意,您可以使用Python的glob模块来简化此过程。
import glob
print(glob.glob('images/*.png'))

原因

当你在Python中遍历一个列表时,背后实际上是在遍历该列表的索引。 当你真正删除这些项时,你会发现这是一个巨大的问题:

l = [1, 2, 2, 3]:
for x in l:
    if x%2 == 0:
        l.remove(x)
    print('x == {}'.format(x))
print('l == {}'.format(l))

你可以从这里打印的内容看出第二个2被跳过了,同时l的值为[1, 2, 3]。这是因为每当到达并移除第一个2时,索引就变成了1(第二个元素)。在下一次迭代中,索引是2。此时,l == [1,2,3],因此x == 3。如果你运行这段代码,它可能比这个解释更明显。

谢谢,这解释了为什么它不起作用。应该早点看到它。 - imj

19

在迭代列表时不应该修改它们,否则会导致奇怪的问题发生。

最好使用列表推导式替代:

filelist= [file for file in os.listdir('images') if file.endswith('.png')]

相同的概念可以应用于初始方法,只需替换删除步骤。然而,这更符合Pythonic的风格。 - keyser
是的,我总是忘记在Python中可以这样做。 - imj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接