【问题标题】:Subprocess contradiction between two programs:两个程序的子进程矛盾:
【发布时间】:2022-01-25 19:15:58
【问题描述】:

我知道这可能看起来很奇怪,但我试图了解为什么会发生以下情况:

我正在编辑一个 Python 程序,当我运行以下 Python 函数时:

def execute_shell_cmd(cmd):
        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        for c in iter(lambda: process.stdout.read(1), b''): 
            print("type_c = ", type(c))
            sys.stdout.write(c)
        for e in iter(lambda: process.stderr.read(1), b''):
            sys.stdout.write(e)

execute_shell_cmd("ls -l")

我得到 type_c 是“字节”的输出,并且 sys.stdout.write(c) 定期运行并一次打印一个字节。

但是当我从一个独立的程序运行这个函数时,我得到了以下错误:

TypeError: write() argument must be str, not bytes

这怎么可能?

【问题讨论】:

  • 这可能取决于sys.stdout 的打开和/或配置方式,但您没有显示该部分。
  • 在哪里可以配置?是否只是某处写着“some_function(sys.stdout)”的代码?
  • 我的意思是 - 如何配置它以使用字节和字符串?
  • setdefaultencoding 周围有一些 hack,它们基本上已经过时,但仍在一些遗留脚本中使用。如果你在 Windows 上,那么在新月的十字路口挥舞死鸡是有道理的。
  • 如果标准输出被重定向到一个文件,这也可能影响 Python 对文件句柄的看法。在现代 Linux 上,终端的输出通常是 UTF-8,但如果您需要与上一千年的设备通信,它可以进行不同的配置。

标签: python-3.x subprocess


【解决方案1】:

在 Python 3 中,sys.stdout 始终为 str 类型,其编码由 PYTHONIOENCODING 环境变量(和/或 Windows 上的 PYTHONUTF8)选择。

sys.stdout.buffer (i.e. a TextIOBase::buffer) 是文本编码stdout 流的底层字节流。

由于您正在从子进程读取字节,因此您还需要写入字节类型的流。

for c in iter(lambda: process.stdout.read(1), b''): 
    sys.stdout.buffer.write(c)

另一方面,如果您确实希望使用文本,you may wish to configure the subprocess object to decode output to strings

【讨论】:

    猜你喜欢
    • 2020-09-12
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    • 2017-09-12
    • 2011-02-03
    • 1970-01-01
    • 2017-11-06
    • 2016-02-21
    相关资源
    最近更新 更多