Python批量合并成对PDF时第二个for循环为何不从起始位置遍历?
Python批量合并成对PDF时第二个for循环为何不从起始位置遍历?
嗨,我来帮你把这个问题理清楚~
你遇到的核心问题其实和glob()返回的对象类型有关:Path.glob()返回的是生成器(generator),而不是普通的列表。生成器有个关键特性——它只能被遍历一次,遍历完之后就“耗尽”了,里面再也没有元素可以取出来了。
看你的代码:
fileList1 = Path(folder).glob('*text1.pdf') fileList2 = Path(folder).glob('*text2.pdf')
这两个变量都是生成器。当第一次执行外层循环(遍历fileList1)时,内层循环会把fileList2的所有元素从头到尾遍历一遍,找到匹配的文件后break。但这时候fileList2这个生成器已经被“用光”了,指针停在了最后一个元素的位置。等到外层循环进入第二次迭代时,再去遍历fileList2,它已经没有任何元素可以返回了,自然不会从头开始。
最简单的修复方法
把生成器转换成列表,这样每次遍历都是从头读取列表里的元素:
# 把glob返回的生成器转成列表 fileList1 = list(Path(folder).glob('*text1.pdf')) fileList2 = list(Path(folder).glob('*text2.pdf'))
这样每次内层循环遍历fileList2时,都是从列表的第一个元素开始,就能正常匹配每一对文件了。
更高效的优化建议
其实嵌套循环的方式效率有点低(如果文件多的话,每次都要遍历整个fileList2),你可以换个思路:先把text2的文件按匹配字符串做成字典,然后直接通过key查找对应的文件,这样更高效。
比如修改代码如下:
def mergeFiles(folder): folder = os.path.abspath(folder) # 转成列表并构建text2文件的字典 fileList1 = list(Path(folder).glob('*text1.pdf')) fileList2 = list(Path(folder).glob('*text2.pdf')) # 构建匹配字符串到文件路径的字典 text2_dict = {} folderLength = len(folder) + 1 fileNameArea = folderLength + 12 for filename2 in fileList2: string2 = str(filename2)[folderLength:fileNameArea].lower() text2_dict[string2] = str(filename2) outputFolderPath = folder + '\\somefolder' p = Path(outputFolderPath) if not p.exists(): os.makedirs(outputFolderPath) n = 0 print(f'Adding files in {outputFolderPath}...') for filename1 in fileList1: n += 1 string1 = str(filename1)[folderLength:fileNameArea].lower() # 直接从字典里找对应的text2文件 if string1 in text2_dict: file2Out = text2_dict[string1] outputName = 'D' + \ str(filename1)[folderLength + 4: folderLength + 6].upper() + \ '_' + str(filename1)[folderLength + 9: folderLength + 12] + \ '_text3.pdf' outputName = outputFolderPath + '\\' + outputName file1Out = str(filename1) pdfMerge([file1Out, file2Out], outputName) print(f'{n}. {os.path.basename(outputName)}') print('Done.')
这样既解决了生成器的问题,又提升了代码的运行效率。
备注:内容来源于stack exchange,提问作者Pacho
相关产品推荐
相关产品推荐

