使用子进程在 Python 中运行 ghostscript 不起作用

Posted

技术标签:

【中文标题】使用子进程在 Python 中运行 ghostscript 不起作用【英文标题】:Running ghostscript in Python using subprocess not working 【发布时间】:2017-08-25 22:45:17 【问题描述】:

好的,如果有人想尝试使 subprocess.Popen 与 ghostscript 一起将此 pdf 文件转换为 txt 文件,这是我的 input.pdf 文件的链接,我已经根据您的回答尝试了所有我能想到的至今。

Link to input.pdf file

再次,直接从命令行执行 ghostscript 可以正常工作,这就是我通过 cmd 行得到的:

C:\Misc>gswin32c -dBATCH -dNOPAUSE -sPageList=1- -sDEVICE=txtwrite -sOutputFile=
    output.txt input.pdf
    GPL Ghostscript 9.21 (2017-03-16)
    Copyright (C) 2017 Artifex Software, Inc.  All rights reserved.
    This software comes with NO WARRANTY: see the file PUBLIC for details.
    Processing pages 1-.
    Page 1
    Page 2
    Page 3
    Page 4
    Page 5

但是以下 Python 代码返回非零退出状态 1. 在 subprocess.check_output() 中,我已删除文件名变量并直接放入文件名路径以使事情更简单。

import subprocess, os

#path for ghostscript executable
gs_path = 'C:\\Program Files\\gs\\gs9.21\\bin'

# dir where pdfs are located
dir_name = 'C:\\Misc'

# pdf to extract text from
file_name = os.path.join(dir_name,'input.pdf')

# output text file name
outfile_name = os.path.join(dir_name,'output.txt')

os.chdir(dir_name)


subprocess.check_output(['gswin32c',
'-dBATCH', '-dNOPAUSE', '-sPageList=1-', 'sDEVICE=txtwrite',
'-sOUTPUTFILE=C:\\Misc\\output.txt',
'C:\\Misc\\input.pdf'])

Python 的完整输出是(Anaconda Python 3.5):

runfile('I:/Downloads/0.data/help_pdf.py', wdir='I:/Downloads/0.data')
Traceback (most recent call last):

  File "<ipython-input-26-0ba7dc571302>", line 1, in <module>
    runfile('I:/Downloads/0.data/help_pdf.py', wdir='I:/Downloads/0.data')

  File "C:\Custom_Programs\Anaconda\lib\site-packages\spyder\utils\site\sitecustomize.py", line 688, in runfile
    execfile(filename, namespace)

  File "C:\Custom_Programs\Anaconda\lib\site-packages\spyder\utils\site\sitecustomize.py", line 101, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "I:/Downloads/0.data/help_pdf.py", line 28, in <module>
    'C:\\Misc\\input.pdf'])

  File "C:\Custom_Programs\Anaconda\lib\subprocess.py", line 316, in check_output
    **kwargs).stdout

  File "C:\Custom_Programs\Anaconda\lib\subprocess.py", line 398, in run
    output=stdout, stderr=stderr)

CalledProcessError: Command '['gswin32c', '-dBATCH', '-dNOPAUSE', '-sPageList=1-', 'sDEVICE=txtwrite', '-sOUTPUTFILE=C:\\Misc\\output.txt', 'C:\\Misc\\input.pdf']' returned non-zero exit status 1

好像 input.pdf 文件路径有问题。

【问题讨论】:

如果ghostscript的用法真的如你所说,它不能写入带有空格的文件名。它可以写入带有空格的文件名。因此,声称可以在同一个参数中传递两个不同的文件名并用空格分隔它们的说法显然是错误的。 另外,如果语法是你所声称的,文档将告诉人们运行-sOutputFile='tiger.png tiger.eps',并用引号告诉外壳程序将两个文件名作为 argv 数组中单个元素的一部分传递。它没有。 'sDEVICE=' 需要是'-sDEVICE=';缺少领先的- 【参考方案1】:

您误解了上游文档。当它告诉你时:

gs -dSAFER -dBATCH -dNOPAUSE -sDEVICE=png16m -dGraphicsAlphaBits=4 \
    -sOutputFile=tiger.png tiger.eps

-sOutputFile=tiger.pngtiger.eps 是两个独立的参数,您需要将它们传递到不同的数组位置。


以下代码已在 MacOS 上使用您给定的input.pdf 成功测试:

#!/usr/bin/env python3.5
import subprocess, sys

gs = 'gswin32c' if (sys.platform == 'win32') else 'gs'
file_name = 'input.pdf'
outfile_name = 'output.txt'

subprocess.check_output([gs,
    '-dBATCH', '-dNOPAUSE', '-sPageList=1-', '-sDEVICE=txtwrite',
    '-sOUTPUTFILE=%s' % (outfile_name,), file_name])

请注意,-sDEVICE=- 开头,以前不是这样。

【讨论】:

我认为可能是这种情况,并尝试将输出和输入文件指定为列表的单独条目,如下所示: subprocess.check_output(["gswin32c", '-ps2ascii', '- sPageList=1-'、'-dNOPAUSE'、'-dBATCH'、'sDEVICE=txtwrite'、"-sOUTPUTFILE=C:\\Misc\\output.txt"、"C:\\Misc\\input.pdf" ],shell=True) 但这也不起作用。 shell=True 不会。把它关掉。 “ps2ascii”开关也没有意义。曾几何时,您可以使用 ps2ascii 程序(与命令行开关不同)来提取文本,但我们已经删除了该程序,现在您应该(照原样)使用 txtwrite 设备。但这不需要名为“ps2ascii”的开关。 天哪,一百万年后我可能不会在 sDEVICE 上发现那个丢失的“-”。现在它正在工作,非常感谢。

以上是关于使用子进程在 Python 中运行 ghostscript 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

使用 python 子进程在实例上运行 gsutil - 访问权限?

python concurrent.futures 使用子进程,运行几个python脚本

检查 python 中正在运行的子进程的标准输出

尝试在python子进程中运行rsync时出现意外的远程arg错误

并行运行多个子进程 - python 2.7

python子进程模块的动态输出