【问题标题】:Python not getting raw binary from subprocess.check_callPython 没有从 subprocess.check_call 获取原始二进制文件
【发布时间】:2016-09-11 18:02:22
【问题描述】:

如何让 subprocess.check_call 给我一个命令的原始二进制输出,它似乎在某处编码不正确。

详情:

我有一个返回如下文本的命令:

some output text “quote” ...

(那些引号是 unicode e2809d)

这是我调用命令的方式:

f_output = SpooledTemporaryFile()
subprocess.check_call(cmd, shell=True, stdout=f_output)
f_output.seek(0)
output = f_output.read()

问题是我明白了:

>>> repr(output)
some output text ?quote? ...
>>> type(output)
<str>

(如果我称 'ord' 为 '?' 我得到 63。) 我在 Linux 上使用 Python 2.7。

注意:在 OSX 上运行相同的代码对我来说可以正常工作。问题是当我在 Linux 服务器上运行它时。

【问题讨论】:

  • 被调用程序可能会根据标准输出调整其输出。如何打开一个常规文件并查看实际写入了哪些字节。顺便说一句,SpooledTemporaryFile 已经结束了。 “假脱机”部分仅适用于从 python 编写的内容。当您获得文件描述符时,它会将其更改为常规临时文件。没有使用额外的 StringIO 缓冲区。
  • 我写了一个快速的 python 程序,它可以输出 utf-8 字符串,你的程序对我有用。
  • 尝试在 shell 中运行命令并重定向到文件。如果您安装了vim,您还应该安装xxd,它可以显示文件十六进制转储。在您的示例文本中,utf-8 输出应如下所示:0000000: 736f 6d65 206f 7574 7075 7420 7465 7874 some output text 0000010: 20e2 809c 7175 6f74 65e2 809d 202e 2e2e ...quote... ... 左引号为 e2 80 9c,右引号为 e2 80 9d
  • 另一种思考方式是,由于 python 2.7 文件读取了一个 ascii ?,它就在被读取的文件中。所以,程序没有写出你认为写的字符串。
  • @tdelaney,你在 osx 上试过了吗?它实际上对我在 OSX 上正常工作。我会更新我的问题。当我直接运行命令行时,它会将我写的内容打印到控制台。我可以尝试让它重定向到一个文件,但我不知道会显示什么。

标签: python python-2.7 unicode subprocess


【解决方案1】:

哇,这是有史以来最奇怪的问题,但我已经解决了!

事实证明,它正在调用的程序(一个 java 程序)会根据调用位置返回不同的编码!

Dev osx 机器,很好地返回字符,Linux 服务器从命令行,很好地返回它们,从 Django 应用程序调用,不变成“?”。

为了解决这个问题,我最终在命令中添加了这个参数:

-Dfile.encoding=utf-8

I got that idea here,它似乎工作。还有一种方法可以在内部修改 Java 程序来做到这一点。

对不起,我责怪 Python!你们的想法是对的。

【讨论】:

  • 您是否尝试过按照我在回答中的建议修复您的区域设置 (locale.getpreferredencoding())(在与您要运行的代码相同的上下文中检查它们)?
【解决方案2】:

重定向 (stdout=file) 发生在文件描述符级别。如果您在文件本身(而不是 REPL)中看到 ? 而不是 ,则 Python 与写入文件的内容无关。

如果它在 OS X 上运行而在 Linux 服务器上“不运行”,则可能的原因是环境不同,请检查 LC_ALL、LC_CTYPE、LANG envvars—python、/bin/sh(由于 shell=True ),如果未设置环境(C,POSIX 语言环境),cmd 可能会使用您的语言环境编码,即 ASCII。

从子进程中获取“原始二进制文件”:

#!/usr/bin/env python
import subprocess

raw_binary = subprocess.check_output(['cmd', 'arg 1', 'arg 2'])
print(repr(raw_binary))

注意:

  • 没有shell=True——除非必要,否则不要使用它
  • 如果检测到输出不是 tty example,许多程序可能会改变其行为。

【讨论】:

    猜你喜欢
    • 2019-07-26
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 2021-05-11
    • 1970-01-01
    • 2013-07-02
    • 1970-01-01
    相关资源
    最近更新 更多