【问题标题】:How can I export binary data from Python subprocess command through STDOUT?如何通过 STDOUT 从 Python 子进程命令导出二进制数据?
【发布时间】:2016-07-13 18:23:05
【问题描述】:

我正在尝试使用 Ghostscript 重新保存 PDF(以纠正 PyPDF2 无法处理的错误)。我用subprocess.check_output 调用Ghostscript,我想将原始PDF 作为STDIN 传递,并将新的PDF 导出为STDOUT。

当我将 PDF 保存到文件中并重新读取时,它工作正常。当我尝试从 STDOUT 传递文件时,它不起作用。我认为这可能是一个编码问题,但我不想将任何内容编码为文本,我只想要二进制数据。也许有一些关于编码的东西我不明白。

如何使 STDOUT 数据像文件数据一样工作?

import subprocess
from PyPDF2 import PdfFileReader
from io import BytesIO
import traceback

input_file_name = "SKMBT_42116071215160 (1).pdf"
output_file_name = 'saved2.pdf'
# input_file = open(input_file_name, "rb") # Moved below.

# Write to a file, then read the file back in. This works.
try:
    ps1 = subprocess.check_output(
        ('gs', '-o', output_file_name, '-sDEVICE=pdfwrite', '-dPDFSETTINGS=/prepress', input_file_name),
        # stdin=input_file # [edit] We pass in the file name, so this only confuses things.
    )
    # I use BytesIO() in this example only to make the examples parallel.
    # In the other example, I use BytesIO() because I can't pass a string to PdfFileReader().
    fakeFile1 = BytesIO()
    fakeFile1.write(open(output_file_name, "rb").read())
    inputpdf = PdfFileReader(fakeFile1)
    print inputpdf
except:
    traceback.print_exc()

print "---------"
# input_file.seek(0) # Added to address one comment. Removed while addressing another.
input_file = open(input_file_name, "rb")

# Export to STDOUT. This doesn't work.
try:
    ps2 = subprocess.check_output(
        ('gs', '-o', '-', '-sDEVICE=pdfwrite', '-dPDFSETTINGS=/prepress', '-'),
        stdin=input_file,
        # shell=True # Using shell produces the same error.
    )
    fakeFile2 = BytesIO()
    fakeFile2.write(ps2)
    inputpdf = PdfFileReader(fakeFile2)
    print inputpdf
except:
    traceback.print_exc()

输出:

   **** The file was produced by:
   **** >>>> KONICA MINOLTA bizhub 421 <<<<
<PyPDF2.pdf.PdfFileReader object at 0x101d1d550>
---------
   **** The file was produced by:
   **** >>>> KONICA MINOLTA bizhub 421 <<<<
Traceback (most recent call last):
  File "pdf_file_reader_test2.py", line 34, in <module>
    inputpdf = PdfFileReader(fakeFile2)
  File "/Library/Python/2.7/site-packages/PyPDF2/pdf.py", line 1065, in __init__
    self.read(stream)
  File "/Library/Python/2.7/site-packages/PyPDF2/pdf.py", line 1774, in read
    idnum, generation = self.readObjectHeader(stream)
  File "/Library/Python/2.7/site-packages/PyPDF2/pdf.py", line 1638, in readObjectHeader
    return int(idnum), int(generation)
ValueError: invalid literal for int() with base 10: "7-8138-11f1-0000-59be60c931e0'"

【问题讨论】:

  • 在 Windows 上,标准输出需要配置为二进制,如下所示:stackoverflow.com/questions/2374427/…。不确定它是否有帮助。值得一试。
  • 值得一提,但我认为这不是本案的解决方案。我使用的是 OS X,但我不知道可以更改的类似设置。
  • 不确定,但您在两次通话之间不回退 input_file 是否正常? (一个有效,一个无效)
  • 我发现没关系(我也尝试使用两个文件对象只是为了查看)。不过,我编辑了我的代码以获得良好的效果。
  • 我认为 PyPDF 必须倒带它。但实际上,在第一个示例中没有必要使用input_file,因为输入是作为文件名而不是STDIN 给出的,所以我删除了它。 (还是不行。)

标签: python shell subprocess


【解决方案1】:

事实证明,这与 Python 无关。这是一个 Ghostscript 错误。正如这篇文章中指出的那样:Prevent Ghostscript from writing errors to standard output,Ghostscript 将错误写入标准输出,这会破坏通过管道输出的文件。

感谢@Jean-François Fabre,他建议我查看二进制文件。

【讨论】:

  • 请将此答案标记为已接受,以便此问题不再出现未解决。也许也重新命名这个问题?谢谢。
  • 当我这样做时,它说:“明天你可以接受自己的答案”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-19
  • 2012-01-13
  • 2019-06-02
  • 2011-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多