【问题标题】:How would you write an `is_pdf(path_to_file)` function in Python?你将如何在 Python 中编写一个 `is_pdf(path_to_file)` 函数?
【发布时间】:2020-10-08 21:44:07
【问题描述】:

我有一个 Django 项目,它使用 Java 作为后台任务创建 PDF。有时该过程可能需要一段时间,因此客户端使用这样的轮询:

  1. 第一个请求启动构建过程并返回None
  2. 每个后续请求都会检查 PDF 是否已构建。
    • 如果是,则返回 PDF。
    • 如果没有,它会再次返回None,并且客户端会安排另一个请求在 n 秒内再次检查。

我的问题是我不知道如何检查 PDF 是否已完成构建。 Java 进程分阶段创建文件。如果我只是检查 PDF 是否存在,那么返回的 PDF 通常是无效的,因为它仍在构建中。所以,我需要一个 is_pdf(path_to_file) 函数,如果文件是有效的 PDF,则返回 True,否则返回 False

如果可能,我想在没有库的情况下执行此操作,但如有必要,我会使用库。

我在 Linux 上。

这是一个使用pdfminer 的解决方案,但对我来说似乎有点矫枉过正。

from pdfminer.high_level import extract_text

def is_pdf(path_to_file):
    """Return True if path_to_file is a readable PDF"""
    try:
        extract_text(path_to_file, maxpages=1)
        return True
    except:
        return False

我希望有一个解决方案,它不需要安装大型库来检查文件是否是有效的 PDF。

【问题讨论】:

  • 还有另一个线程用于使用 python 验证 pdf 文件。我认为这个答案对你来说应该足够了:stackoverflow.com/a/32654661/6430256
  • 谢谢,但我已经查看过它并没有答案。 PyPDF2 不再维护。可能有使用ReportLab 的解决方案,但我不知道该怎么做。使用 Popen() 的解决方案看起来很有希望,但我无法实现。
  • 我明白了,Popen 解决方案适用于 linux 环境。我正在检查 reportlab 模块,但到目前为止我还没有看到任何有用的东西来验证 pdf。
  • 您仍然可以从操作系统中找出 Java 进程的 PID 是什么,并对其进行监控。当然,如果它是一项始终运行的服务,那么您可能就不走运了。
  • 我更新了我的答案,为 PDFParser 和 PDFDocument 添加了另一个示例。如果 open() 函数不抛出异常,PDFDocument 或 PDFParser 可能会抛出异常。如果没有抛出异常,PDFDocument.info 属性可能有用。

标签: python django pdf


【解决方案1】:

我找到了这个 pypi.org/project/pdfminer.six 。我制作了一个简单的例子。看看对你有没有用。 a.pdf 是一个空文件。我不知道当试图读取一个仍在被另一个程序处理的 pdf 文件时它会做什么。

from pdfminer.high_level import extract_text

try:
 text = extract_text("D:\\a.pdf")
 print(text)
except :
 print("invalid PDF file")
else:
 pass

--- 更新 --

另外,我在 pdfminer github 上看到了 PDFDocument 的示例, https://github.com/pdfminer/pdfminer.six/blob/develop/tools/pdfstats.py 在第 53 行。

我制作了一个类似的示例代码:

from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfparser import PDFParser

try:
 pdf_file = open("D:\\a.pdf", 'rb')
 parser = PDFParser(pdf_file)
 password = ''
 document = PDFDocument(parser, password)
 print(document.info)
 print(document.xrefs)
except :
 print("invalid PDF file")
else:
 pass

在我的例子中,因为 a.pdf 是空的; open() 函数抛出异常。在您的情况下,我猜它可以打开文件,但 PDFParser 或 PDFDocument 可能会引发异常。如果没有抛出异常,PDFDocument.info 属性可能有用。

-- 更新 2--

我已经意识到文档对象具有外部参照属性。 PdfParser 类中有一个解释:“它还在每个 PDF 文件的末尾读取外部参照。”检查 document.xrefs 的值可能很有用。

【讨论】:

  • 这与我在您最初发表评论后添加到问题中的解决方案非常相似。这是迄今为止我想出的最好的解决方案,但它似乎有点矫枉过正。如果 PDF 很大,我的 PDF 很大,它必须提取所有文本以查看它是否是有效的 PDF。
  • 有人投了反对票,大概是因为它与我添加到问题中的代码非常相似,但为了公平对待@AntiqTech,我在他们的原始评论之后添加了该解决方案。
  • 啊,我没有意识到您添加了您的问题。当我检查 pdfminer 时,我在它的 github 上找到了这个文件。 github.com/pdfminer/pdfminer.six/blob/develop/tools/pdfstats.py 第 53 行有这个 PDFDocument() 示例。 PDFDocument 对象具有 info 属性。也许你可以尝试它来提取信息。如果它抛出异常,您可能会认为它是无效的。我会将示例代码添加到我的答案中。
  • 这很有效,可能是一个不错的选择。我希望它比从 PDF 中提取所有文本更有效。我会稍等片刻,看看是否有人可以提供不涉及安装和导入这么大的库的答案。
  • 检查xrefs 是不必要的,因为如果 PDF 无效,PDFDocument() 会失败。仅供参考,我已将问题中的代码更新为包含 maxpages=1,因此当 PDF 有效时,它不会提取整个 PDF 的文本。
【解决方案2】:

我怀疑您可以编写一个脚本给自己或团队分发电子邮件,然后简单地列出目录中的所有文件。但是,如果您只是询问如何在不安装模块的情况下本地搜索目录。我会导入 os 和 re。

# ***** Search File *****
files = os.listdir(r"C:\Users\PATH")
print(files)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-02
    • 2011-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多