通过子进程调用 GhostScript 无法创建输出文件

Posted

技术标签:

【中文标题】通过子进程调用 GhostScript 无法创建输出文件【英文标题】:GhostScript fails to create output file when called via subprocess 【发布时间】:2017-03-23 17:43:46 【问题描述】:

我的 PDF 已损坏,当我通过终端输入此命令时:

gs -o "/Path/to/required/repaired_file.pdf" -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress "/Path/to/required/corrupted_file.pdf"

成功创建了一个新的(未损坏的)PDF 文件 (repaired_file.pdf)。但是,当我尝试从 subprocess.call() 或 subprocess.Popen() 中运行此命令时,命令失败:

Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 19 2015, 20:38:52) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> import subprocess
>>> subprocess.call(["/usr/local/bin/gs", "-o", "\"/Path/to/required/repaired_file.pdf\"", "-sDEVICE=pdfwrite", "-dPDFSETTINGS=/prepress", "\"/Path/to/required/corrupted_file.pdf\""], stderr=sys.stdout)
GPL Ghostscript 9.20 (2016-09-26)
Copyright (C) 2016 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
GPL Ghostscript 9.20: **** Could not open the file "/Path/to/required/repaired_file.pdf" .
**** Unable to open the initial device, quitting.
1

所需解决方案:

任何解决方案都会很棒,但是由于已知的安全问题,我不喜欢在我的子流程语句中使用shell=True

我自己尝试解决的方法是:

为方便起见,我在整个基本目录 + 所有文件中都使用了chmod 777,因此我确信这不是版权问题。 因为我知道有时需要使用子进程调用中使用的任何命令的完整路径,所以我也尝试了许多变体,从我在终端中使用的简单 "gs" 到完整的 "/usr/zsh", "/usr/local/bin/gs"子进程调用但无济于事。 我已经对我的语法进行了三重检查(是的,我还尝试将我的整个命令包装在一个变量中并使用 shlex.split(command) 来双重确定我的语法,所以我很确定它是不是语法问题。

任何帮助表示赞赏!

【问题讨论】:

【参考方案1】:

您明确地将引号添加到路径中,因此gs 尝试查找其路径以" 开头和结尾的文件。不出所料,它找不到它。假设您使用的是 Linux 或其他类 Unix 系统 (*),在命令行中,引号是 shell 的进程,gs 使用不带引号的参数调用。

只需使用:

subprocess.call(["/usr/local/bin/gs", "-o", "/Path/to/required/repaired_file.pdf", 
    "-sDEVICE=pdfwrite", "-dPDFSETTINGS=/prepress", "/Path/to/required/corrupted_file.pdf"],
    stderr=sys.stdout)

(*)在 Windows 上会有所不同

【讨论】:

啊,美妙的语法世界,我没有在我的实际脚本中使用那些"(其中文件名是从多个字符串变量构建的)。但是,如果我完整地编写文件路径,不带引号,它确实 确实 工作,所以..必须意味着在我的实际脚本中的某个地方我确实仍然以某种方式弄乱了语法..谢谢!

以上是关于通过子进程调用 GhostScript 无法创建输出文件的主要内容,如果未能解决你的问题,请参考以下文章

孤儿进程和僵尸进程

linux下为什么不能有孤儿进程

僵尸进程和孤儿进程-(转自Anker's Blog)

僵尸进程与孤儿进程

如何在ghostscript中调用字体目录

从 PHP 调用 Ghostscript:无法打开初始设备