在 python 中使用 soffice,Command 在终端中有效,但在 Python 子进程中无效

Posted

技术标签:

【中文标题】在 python 中使用 soffice,Command 在终端中有效,但在 Python 子进程中无效【英文标题】:Using soffice within python, Command works in terminal but not in Python subprocess 【发布时间】:2016-06-12 08:38:04 【问题描述】:

我在 Python 中遇到了最令人沮丧的 libreoffice 问题

当我在终端中运行以下命令时,我完全没有问题,pdf 文件会在我想要的地方生成,并且生活很美好:

cd /Applications/LibreOffice.app/Contents/MacOS/

./soffice --convert-to pdf --outdir output_folder path_to_docx_file/title.docx

但是,当我尝试将其添加到我的 python 脚本中时:

SOFFICE = r'/Applications/LibreOffice.app/Contents/MacOS/soffice'

subprocess.Popen([SOFFICE, "--convert-to", "pdf", "--outdir", "output_folder ", "path_to_docx_file/title.docx"])

我收到一条错误消息:

错误:无法加载源文件

我已经尝试打开所有二进制文件和文件的所有权限,但这在 python 脚本中仍然不起作用。我究竟做错了什么?

【问题讨论】:

【参考方案1】:

对我来说,这只是缺少“libreoffice-writer”包的问题。因此,如果您使用的是 Debian:

apt-get 安装 libreoffice-writer

【讨论】:

【参考方案2】:

我也遇到过同样的问题。 (我使用了绝对路径,所以亚历克西斯的回答并没有解决我的问题)。

经过大量实验,我发现使用os.system 代替subprocess.Popen 不会引发同样的问题,所以也许这可以作为一个快速解决方案。

更详细地说,我创建了以下适用于我的环境的方法。

def makePdfFromDoc_linux_batch(input_folder_path, target_folder_path):
    input_folder_files = os.path.join(input_folder_path, "*.doc")
    os.system("/Applications/LibreOffice.app/Contents/MacOS/soffice --headless --convert-to pdf --outdir " + target_folder_path + " " + input_folder_files)

但是,我不知道这个问题的原因。由于os.system 显示不同的行为,它可能取决于 subprocess.Popen 为运行命令而生成的环境 - 但我没有实际证据。

我发现this blog post,遇到同样的问题似乎出现在红宝石环境中。它并没有真正帮助我理解问题的根源,但实际上我很着急,所以也许它可以对你更有帮助。

【讨论】:

【参考方案3】:

这是因为您需要更改当前工作目录,而不仅仅是给出命令的绝对路径。

subprocess.Popen(["/Applications/LibreOffice.app/Contents/MacOS/soffice", "--convert-to", "pdf", "--outdir", "output_folder ", "path_to_docx_file/title.docx"])

应替换为:

subprocess.Popen(["soffice", "--convert-to", "pdf", "--outdir", "output_folder ", "path_to_docx_file/title.docx"], cwd="/Applications/LibreOffice.app/Contents/MacOS/")

即使它看起来很相似,这两个调用之间也有一个主要区别:当前工作目录。

使用脚本:

subprocess.Popen(["/Applications/LibreOffice.app/Contents/MacOS/soffie", "--convert-to", "pdf", "--outdir", "output_folder ", "file.docx"])

如果您在 ~ 目录中调用 python 脚本,它将尝试访问 ~/file.docx。

但是,在第二个中:

subprocess.Popen(["soffice", "--convert-to", "pdf", "--outdir", "output_folder ", "file.docx"], cwd="/Applications/LibreOffice.app/Contents/MacOS/")

它将尝试访问“/Applications/LibreOffice.app/Contents/MacOS/file.docx”中的文件,这与您使用 cd 命令所做的行为相同(实际上 cd 命令改变了当前目录,所以给出 cwd 参数与进行cd 调用相同)。

您可以也对所有文件使用绝对路径,它也可以解决问题,但这不是您想要做的。这取决于您尝试构建的软件及其用途。

这就是提示说文件不存在的原因。程序在WHERE_YOU_CALL_THE_SCRIPT/path_to_docx_file/title.docx 中找不到文件,因为我认为该文件在/Applications/LibreOffice.app/Contents/MacOS/path_to_docx_file/title.docx 中。

【讨论】:

我不认为这就是 OP 的意思。我遇到了同样的问题。如果我在 bash 中运行“/Applications/LibreOffice.app/Contents/MacOS/soffice --convert-to pdf --outdir /Users/andrea/pdf_conversion/tempOutput/ /Users/andrea/pdf_conversion/tempInput/*”,它可以工作.如果我尝试使用 subprocess.Popen 在 Python 中运行它,使用完全相同的字符串(将其拆分为空格)会引发“无法加载源文件”问题。

以上是关于在 python 中使用 soffice,Command 在终端中有效,但在 Python 子进程中无效的主要内容,如果未能解决你的问题,请参考以下文章

无法读取使用 soffice 命令转换 pdf 后得到的 .docx 文件

使用 soffice 进行命令行 pdf 打印

使用 soffice 命令行将 xls 转换为分号分隔的 csv

使用 soffice 将 doc 转换为 docx 不起作用

如何检测并杀死楔入的 soffice.bin 进程?

soffice.exe 将 odt 转换为 PDF/A