Python 未从 subprocess.check_call 获取原始二进制文件

Python not getting raw binary from subprocess.check_call

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

详情:

我有一个命令 returns 文本如下:

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。) 我在 Python 2.7 Linux.

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

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

如果它在 OS X 上工作并且它在 Linux 服务器上 "doesn't work" 那么可能的原因是环境的差异,检查 LC_ALL, LC_CTYPE,LANG envvars—python,/bin/sh(由于 shell=True),如果未设置环境,cmd 可能会使用 ASCII 语言环境编码(C , POSIX 语言环境).

要从子进程中获取 "raw binary":

#!/usr/bin/env python
import subprocess

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

注:

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

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

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

Dev osx 机器,returns 字符很好,Linux 来自命令行的服务器,returns 它们很好,从 Django 应用程序调用,不变成“ "s.

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

-Dfile.encoding=utf-8

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

对不起我错怪了Python!你们的想法是对的。