从列表中删除项目的异常行为

时间:2019-11-14 01:02:42

标签: python

对于初学者来说,我是python和编码方面的新手。

我正在尝试从正在创建的zip文件夹中删除desktop.ini文件。我正在使用以下方法来做到这一点

if 'desktop.ini' in item:
     contents.remove(item)
     continue

但是,desktop.ini之后的列表中的项目也被删除了,我也不知道为什么。任何想法为什么会这样?

如果需要更多上下文,这是整个脚本

import shutil
import zipfile
import tempfile
from distutils.dir_util import copy_tree

def fileList(fileName):
    files = list()
    for (dirpath, dirnames, filenames) in os.walk(fileName):
        files += [os.path.join(dirpath, file) for file in filenames]
    return files

print("What version are these macros? ")
versNo = str(input())
path = os.path.dirname(os.path.realpath(__file__))
mac = 'macros'

with tempfile.TemporaryDirectory() as macfolder:
    copy_tree(os.path.join(path,mac),macfolder)
    with zipfile.ZipFile(os.path.join(path, "Release Assets",'Nautilus_Macros_'+versNo+'.zip'),'a') as maczip:
        contents = fileList(macfolder)
        #print(contents)
        for item in contents:
            #print(item)
            if 'desktop.ini' in item:
                    contents.remove(item)
                    continue
            #print(item)
            f = open(item,'r+')
            lines = f.readlines()
            f.seek(0)
            f.write('; Macro for the Nautilus 3D printer by Hydra Research \n')
            f.write('; Version: '+versNo+' \n \n')
            for line in lines:
                f.write(line)
            f.close()
            print(item)
            maczip.write(os.path.join(macfolder, item), os.path.relpath(item, macfolder))
    maczip.close()

1 个答案:

答案 0 :(得分:0)

在遍历列表(或其他集合)中的任何内容时,警笛声应该响亮,警告灯应闪烁。

考虑一下如何迭代列表实际上是如何工作的:存在一些变量(我们将其称为i),该变量可跟踪当前项目的索引。在循环的每次迭代中,i增加1,并且在i >= len(contents)时循环停止。

当您从列表中的索引i删除元素时,该元素之后的所有元素都向左移动1,以填充已删除元素所在的“间隙”。先前在索引i + 1处的元素现在在索引i处。 但是i仍增加1,为下一次迭代做好准备,并且您下一个读取的元素来自索引i + 1。该元素以前在索引i + 2处为,因此您已跳过了该元素。

由于这种原因,在for循环中迭代集合时,切勿从集合中添加或删除元素。


在这种情况下,仅使用continue就足以确保该元素不会被写入maczip;它将跳过从contents到下一个元素的循环,因此您也不需要从contents中删除当前元素。通过以下方式更改代码:

if 'desktop.ini' in item:
    # don't do contents.remove(item)
    continue