【问题标题】:Why is data missing when I write to a python subprocess stdin pipe?为什么当我写入 python 子进程标准输入管道时数据丢失?
【发布时间】:2015-09-21 16:25:01
【问题描述】:

我的 python 代码如下所示:

def test():
    pipe = sp.Popen( ["test.sh"], stdin=sp.PIPE)
    data = "".join([chr((s)%17) for s in range(0,33)])
    os.write(pipe.stdin.fileno(), data)
    pipe.stdin.write("endoffile")

if __name__ == "__main__":
    test()

它调用以下简单的 bash shell 脚本,该脚本只是将标准输入写入文件(脚本称为 test.sh)

#!/bin/bash
VALUE=$(cat)

echo "$VALUE" >> /tmp/test.txt

当我运行 python 代码时,我希望 test.txt 包含两次值 0x01..0x10,然后是字符串“endofile”

但是这里是文件的十六进制转储:

0000000: 0102 0304 0506 0708 090a 0b0c 0d0e 0f10  ................
0000010: 0102 0304 0506 0708 090a 0b0c 0d0e 0f65  ...............e
0000020: 6e64 6f66 6669 6c65 0a                   ndoffile.

似乎缺少一个字节(0x10)。

我在这里错过了什么?

--- 更新

将 test() 函数更改为:

def test():
    pipe = sp.Popen( ["test.sh"], stdin=sp.PIPE)
    data = "".join([chr((s)%16+1) for s in range(0,32)])
    os.write(pipe.stdin.fileno(), data)
    pipe.stdin.write("endoffile")

似乎解决了这个问题。 这似乎与将 chr(0) 发送到管道有关。

【问题讨论】:

    标签: python bash pipe subprocess


    【解决方案1】:

    range() 是右侧独占。

    range(0, 33)[0, ..., 32],可能是因为这样你就可以range(0, len(sequence)) 而不会出错。

    由于32 % 17 == 15 == 0x0f,您所期望的字节'\x10' 一开始就不是列表的一部分。

    编辑 1: 输出中还缺少零字符'\x00'。如果您使用VALUE=$(cat)cat 的输出将由 shell 处理。

    SingleUnix/POSIX 似乎对此事保持沉默。然而很明显,您不能将'\0' 作为shell 变量值(或名称)的一部分,因为Unix 环境要求两者都是C-style zero terminated strings。我实际上本来希望VALUE 的值是一个空字符串。

    编辑 2 经过一番挖掘,我可以说至少ash implementation 忽略了'\0' 处理反引号提供的输入。读取输入直到 EOF 和空字符被显式跳过。

    bash 做同样的事情,甚至有一个明确的(即使被注释掉)warning 与事件关联。

    【讨论】:

    • dhke - 你是对的,但是另一个错误是错误的 - 缺少一个条目。我怀疑这是由于通过管道发送 chr(0) - 它被丢弃了。知道为什么吗?
    • @sferic 我什至没有意识到\0 也不见了,谢谢你提醒我。见编辑。
    • 在这个人为的例子中,一个解决方案是让 test.sh 包含一行代码:cat >> /tmp/test.txt
    • 问题不在于cat 的输出会被分词(不是),而是空字节过早地终止了字符串。 Shell 根本不是为处理任意二进制数据而设计的。
    • @chepner 对,= 不进行分词。这实际上让我更加确定这只是一个没有记录的副作用,你不能以任何方式依赖它。
    猜你喜欢
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 2015-08-22
    • 2012-01-18
    相关资源
    最近更新 更多