为什么写入 python 子进程标准输入管道时数据丢失?
Why is data missing when I write to a python subprocess stdin pipe?
我的 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 脚本,该脚本只是将 stdin 写入文件(脚本名为 test.sh)
#!/bin/bash
VALUE=$(cat)
echo "$VALUE" >> /tmp/test.txt
当我 运行 python 代码时,我希望 test.txt 包含值 0x01..0x10 两次,然后是字符串 "endoffile"
但是这里是文件的十六进制转储:
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) 发送到pipe 有关系。
range()
右侧独占
range(0, 33)
是 [0, ..., 32]
,可能是因为这样你可以 range(0, len(sequence))
而不会出现差一错误。
自 32 % 17 == 15 == 0x0f
以来,您期望的字节 '\x10'
一开始就不是列表的一部分。
编辑 1:
输出中还缺少零字符 '\x00'
。如果您使用 VALUE=$(cat)
,cat
的输出将由 shell 处理。
SingleUnix/POSIX似乎对此事保持沉默。但是很明显,您不能将 '[=19=]'
作为 shell 变量值(或相关名称)的一部分,因为 Unix 环境要求两者都是 C-style zero terminated strings。我实际上希望 VALUE
的值是一个空字符串。
编辑 2
经过一些挖掘,我可以说至少 ash
implementation 忽略了 '[=19=]'
处理反引号提供的输入。读取输入直到明确跳过 EOF 和空字符。
bash
做同样的事情,甚至有一个明确的(即使被注释掉)warning 与事件相关联。
我的 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 脚本,该脚本只是将 stdin 写入文件(脚本名为 test.sh)
#!/bin/bash
VALUE=$(cat)
echo "$VALUE" >> /tmp/test.txt
当我 运行 python 代码时,我希望 test.txt 包含值 0x01..0x10 两次,然后是字符串 "endoffile"
但是这里是文件的十六进制转储:
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) 发送到pipe 有关系。
range()
右侧独占
range(0, 33)
是 [0, ..., 32]
,可能是因为这样你可以 range(0, len(sequence))
而不会出现差一错误。
自 32 % 17 == 15 == 0x0f
以来,您期望的字节 '\x10'
一开始就不是列表的一部分。
编辑 1:
输出中还缺少零字符 '\x00'
。如果您使用 VALUE=$(cat)
,cat
的输出将由 shell 处理。
SingleUnix/POSIX似乎对此事保持沉默。但是很明显,您不能将 '[=19=]'
作为 shell 变量值(或相关名称)的一部分,因为 Unix 环境要求两者都是 C-style zero terminated strings。我实际上希望 VALUE
的值是一个空字符串。
编辑 2
经过一些挖掘,我可以说至少 ash
implementation 忽略了 '[=19=]'
处理反引号提供的输入。读取输入直到明确跳过 EOF 和空字符。
bash
做同样的事情,甚至有一个明确的(即使被注释掉)warning 与事件相关联。