Python pypdf将多个pdf文件合并为一个pdf
如果我有1000多个pdf文件需要合并成一个pdfPython pypdf将多个pdf文件合并为一个pdf,python,pypdf,Python,Pypdf,如果我有1000多个pdf文件需要合并成一个pdf input = PdfFileReader() output = PdfFileWriter() filename0000 ----- filename 1000 input = PdfFileReader(file(filename, "rb")) pageCount = input.getNumPages() for iPage in range(0, pageCount): output.addPa
input = PdfFileReader()
output = PdfFileWriter()
filename0000 ----- filename 1000
input = PdfFileReader(file(filename, "rb"))
pageCount = input.getNumPages()
for iPage in range(0, pageCount):
output.addPage(input.getPage(iPage))
outputStream = file("document-output.pdf", "wb")
output.write(outputStream)
outputStream.close()
当input=PdfileReader(文件(filename500+,“rb”))
时,执行上述代码
错误消息:
IOError:[Errno 24]打开的文件太多:
我认为这是一个bug,如果不是,我该怎么办?可能正是它所说的,您正在打开许多文件。
您可以显式使用
f=file(文件名)。。。f、 在循环中关闭()
,或使用with
语句。以便正确关闭每个打开的文件 问题在于,在任何给定时间,您只能打开一定数量的文件。有很多方法可以改变这个(),但我认为您不需要这个
您可以尝试关闭for循环中的文件:
input = PdfFileReader()
output = PdfFileWriter()
for file in filenames:
f = open(file, 'rb')
input = PdfFileReader(f)
# Some code
f.close()
我最近遇到了完全相同的问题,所以我深入研究了PyPDF2,看看发生了什么,以及如何解决它 注意:我假设
filename
是格式良好的文件路径字符串。假设我的所有代码都是相同的
简短的回答
使用PdfFileMerger()
类代替PdfFileWriter()
类。我已尝试提供以下内容,以尽可能接近您的内容:
from PyPDF2 import PdfFileMerger, PdfFileReader
[...]
merger = PdfFileMerger()
for filename in filenames:
merger.append(PdfFileReader(file(filename, 'rb')))
merger.write("document-output.pdf")
长答案
使用PdfFileReader
和PdfFileWriter
的方法是保持每个文件打开,并最终导致Python生成IOError 24。更具体地说,当您向PdfFileWriter
添加页面时,您是在打开的PdfFileReader
中添加对该页面的引用(因此,如果关闭该文件,会出现注意到的IO错误)。Python检测到仍要引用的文件,并且不执行任何垃圾收集/自动关闭文件,尽管重新使用了文件句柄。它们将保持打开状态,直到PdfFileWriter
不再需要访问它们,即在代码中的output.write(outputStream)
要解决此问题,请在内容的内存中创建副本,并允许关闭文件。在我的PyPDF2代码冒险中,我注意到PdfFileMerger()
类已经有了这个功能,所以我没有重新发明轮子,而是选择使用它。不过,我了解到,我最初对PdfFileMerger
的观察不够仔细,它只在特定条件下创建副本
我最初的尝试如下所示,并导致了相同的IO问题:
merger = PdfFileMerger()
for filename in filenames:
merger.append(filename)
merger.write(output_file_path)
查看PyPDF2源代码,我们看到append()
需要传递fileobj
,然后使用merge()
函数,将其最后一页作为新文件位置传递merge()
使用fileobj
执行以下操作(在使用PdfFileReader(fileobj)打开它之前)
:
我们可以看到,append()
选项确实接受字符串,并且在这样做时,假定它是一个文件路径,并在该位置创建一个文件对象。最终结果与我们试图避免的完全相同。一个PdfFileReader()
对象将打开一个文件,直到文件最终被写入
但是,如果我们在路径字符串传递到append()
之前创建文件路径字符串的file对象或路径字符串的PdfFileReader
(请参见编辑2)对象,它将自动为我们创建一个副本作为StringIO
对象,从而允许Python关闭文件
我建议使用更简单的merge.append(file(filename,'rb'))
,因为其他人报告说,即使在调用writer.close()
之后,PdfFileReader
对象也可能在内存中保持打开状态
希望这有帮助
编辑:我假设您使用的是PyPDF2
,而不是PyPDF
。如果您不使用,我强烈建议您切换,因为PyPDF已不再维护,作者已正式批准分阶段开发PyPDF2
如果由于某种原因您无法切换到PyPDF2(许可、系统限制等),则Pdfilemerger
将不可用。在这种情况下,您可以重新使用PyPDF2的合并
功能中的代码(如上所述)将文件的副本创建为StringIO
对象,并在代码中使用该副本代替文件对象
编辑2:先前建议使用的
merge.append(PdfileReader(file(filename,'rb'))
根据注释进行了更改(感谢@Agostino)。pdfrw包一次读取所有文件,因此不会出现打开文件过多的问题。这是一个连接脚本示例
相关部分——假设inputs
是一个输入文件名列表,outfn
是一个输出文件名:
from pdfrw import PdfReader, PdfWriter
writer = PdfWriter()
for inpfn in inputs:
writer.addpages(PdfReader(inpfn).pages)
writer.write(outfn)
免责声明:我是pdfrw的主要作者。我编写此代码是为了帮助回答以下问题:-
import sys
import os
import PyPDF2
merger = PyPDF2.PdfFileMerger()
#get PDFs files and path
path = sys.argv[1]
pdfs = sys.argv[2:]
os.chdir(path)
#iterate among the documents
for pdf in pdfs:
try:
#if doc exist then merge
if os.path.exists(pdf):
input = PyPDF2.PdfFileReader(open(pdf,'rb'))
merger.append((input))
else:
print(f"problem with file {pdf}")
except:
print("cant merge !! sorry")
else:
print(f" {pdf} Merged !!! ")
merger.write("Merged_doc.pdf")
在本文中,我使用了PyPDF2.PdfFileMerger和PyPDF2.PdfFileReader,而不是在使用f.close()、exec output.write(outputStream)时将文件名显式转换为文件对象,提示IO错误。老实说,我还没有读到长答案。不过短答案很好。我注意到我无法删除附加的一些文件,使用调用
writer.append(PdfFileReader(file(filename,'rb'))
,创建一个中间PdfFileReader
对象。即使调用writer.close()
。更简单的调用merge.append(文件名为'rb'))
似乎没有同样的问题。如果文件太大,这不会导致内存问题吗?@Nishant与您在内存中创建的任何对象一样,是的。事实上,如果您将单个PDF文件的容量增加到千兆字节,可能会有更好的解决方案。@好的,谢谢,值得知道。一个小实用程序很有趣选择命名为临时文件vs内存的Action是我在这方面看到的一个很好的解决方案。
import sys
import os
import PyPDF2
merger = PyPDF2.PdfFileMerger()
#get PDFs files and path
path = sys.argv[1]
pdfs = sys.argv[2:]
os.chdir(path)
#iterate among the documents
for pdf in pdfs:
try:
#if doc exist then merge
if os.path.exists(pdf):
input = PyPDF2.PdfFileReader(open(pdf,'rb'))
merger.append((input))
else:
print(f"problem with file {pdf}")
except:
print("cant merge !! sorry")
else:
print(f" {pdf} Merged !!! ")
merger.write("Merged_doc.pdf")