【问题标题】:Converting docx to pdf with pure python (on linux, without libreoffice)使用纯 python 将 docx 转换为 pdf(在 linux 上,没有 libreoffice)
【发布时间】:2018-12-01 14:02:14
【问题描述】:

我正在处理一个尝试开发网络应用程序的问题,其中一部分将上传的 docx 文件转换为 pdf 文件(经过一些处理)。使用python-docx 和其他方法,我不需要安装word 的windows 机器,甚至不需要Linux 上的libreoffice,进行大部分处理(我的网络服务器是pythonanywhere - linux 但没有libreoffice,也没有sudoapt install权限)。但转换为 pdf 似乎需要其中之一。通过在这里和其他地方探索问题,这就是我目前所拥有的:

import subprocess

try:
    from comtypes import client
except ImportError:
    client = None

def doc2pdf(doc):
    """
    convert a doc/docx document to pdf format
    :param doc: path to document
    """
    doc = os.path.abspath(doc) # bugfix - searching files in windows/system32
    if client is None:
        return doc2pdf_linux(doc)
    name, ext = os.path.splitext(doc)
    try:
        word = client.CreateObject('Word.Application')
        worddoc = word.Documents.Open(doc)
        worddoc.SaveAs(name + '.pdf', FileFormat=17)
    except Exception:
        raise
    finally:
        worddoc.Close()
        word.Quit()


def doc2pdf_linux(doc):
    """
    convert a doc/docx document to pdf format (linux only, requires libreoffice)
    :param doc: path to document
    """
    cmd = 'libreoffice --convert-to pdf'.split() + [doc]
    p = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
    p.wait(timeout=10)
    stdout, stderr = p.communicate()
    if stderr:
        raise subprocess.SubprocessError(stderr)

如您所见,一种方法需要comtypes,另一种方法需要libreoffice 作为子进程。除了切换到更复杂的托管服务器之外,还有什么解决方案吗?

【问题讨论】:

  • Python-docx 不需要 Word(也不需要 Windows),因为它几乎可以在其源代码中完成所有工作。 (“几乎全部”,除了一些外部标准模块,例如 XML、ZIP 内容和图像处理。)由于 Python 是图灵完备的语言,您可以做同样的事情来无中生有地创建 PDF,无需外部软件.从前到后阅读the official specifications,您就会知道为什么使用外部程序要容易得多。
  • @usr2564301 当然更简单,但如果不切换服务器,这对我来说不是一个选择
  • 然后找到一个用于创建 PDF 的纯 Python 实现(推荐一个是违反 Stack Overflow 准则的,但您当然可以使用搜索引擎并找到一个适合您的目的和编程水平的),或者滚动您的自己的。但请注意,“每个人”都在使用外部实用程序是有充分理由的——阅读上述规范以了解原因。
  • 为什么不使用通过 python 触发的 api,例如convertapi.com/docx-to-pdf ?还要检查这个问题stackoverflow.com/questions/3815983/…
  • 改用pandoc

标签: python pdf docx pythonanywhere python-docx


【解决方案1】:

PythonAnywhere 帮助页面在此处提供有关使用 PDF 文件的信息:https://help.pythonanywhere.com/pages/PDF

总结:PythonAnywhere 安装了许多用于 PDF 操作的 Python 包,其中一个可以满足您的需求。但是,对我来说,向abiword 发起攻击似乎是最容易的。 shell 命令abiword --to=pdf filetoconvert.docx 会将docx 文件转换为PDF 并在与docx 相同的目录中生成一个名为filetoconvert.pdf 的文件。请注意,此命令将向标准错误流输出一条错误消息,抱怨XDG_RUNTIME_DIR(或者至少对我来说是这样),但它仍然有效,并且可以忽略错误消息。

【讨论】:

  • 我必须做一些测试,看看它是否能在不弄乱文件的情况下工作,但这正是我想听到的答案:) 会报告结果
  • 这也适用于我。它确实创建了一个 pdf 文件(具有相同的文件名),但我也收到了 XDG_RUNTIME_DIR 错误。为了抑制这个错误,我在 bash 控制台中使用了export XDG_RUNTIME_DIR=/tmp/,第二次尝试时错误消失了。最后,为了检查是否转换成功,我从Pythonanywhere下载了pdf文件到本地电脑,打开文件查看内容。全部内容显示成功。
  • 反馈:这工作得相当好(从右到左的语言存在一些问题)但这是目前对我来说最好的解决方案(我最终可能会迁移到谷歌云)。谢谢!
  • 来自 Abiword 的网站:“Windows 用户请注意:由于项目中缺少 Windows 开发人员,因此不再提供可供下载的版本。”
  • @ThomIves 虽然这可能是真的,但这是关于通过 PythonAnywhere 使用 Linux 的问题,因此这里不涉及 Windows 版本。
【解决方案2】:

您可以使用的另一个是libreoffice,但正如第一响应者所说,质量永远不会像使用实际comtypes那样好。

无论如何,在你安装 libreoffice 之后,这里是执行它的代码。

from subprocess import  Popen
LIBRE_OFFICE = r"C:\Program Files\LibreOffice\program\soffice.exe"

def convert_to_pdf(input_docx, out_folder):
    p = Popen([LIBRE_OFFICE, '--headless', '--convert-to', 'pdf', '--outdir',
               out_folder, input_docx])
    print([LIBRE_OFFICE, '--convert-to', 'pdf', input_docx])
    p.communicate()


sample_doc = 'file.docx'
out_folder = 'some_folder'
convert_to_pdf(sample_doc, out_folder)

【讨论】:

  • 这似乎不能很好地并行工作。我创建了 10 个 Popen 实例来转换 10 个 docx 文件,但只得到 5 个 pdf,并且没有任何错误输出。
  • 有趣,我前一阵子做过,但也许可以发布你的代码?
  • 我用我的代码发布了一个问题:stackoverflow.com/questions/66719566/…@dfresh22
猜你喜欢
  • 1970-01-01
  • 2018-09-19
  • 2022-08-17
  • 1970-01-01
  • 2019-03-22
  • 1970-01-01
  • 2018-10-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多