Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么在写入python子进程stdin管道时会丢失数据?_Python_Bash_Pipe_Subprocess - Fatal编程技术网

为什么在写入python子进程stdin管道时会丢失数据?

为什么在写入python子进程stdin管道时会丢失数据?,python,bash,pipe,subprocess,Python,Bash,Pipe,Subprocess,我的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() 它调用以

我的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()
它调用以下简单的bashshell脚本,该脚本只将stdin写入一个文件(该脚本称为test.sh)

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

但是,这里有一个文件的hextump:

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)发送到管道有关。

range()
是右侧独占的

范围(0,33)
[0,…,32]
,可能是因为这样您可以
范围(0,len(序列))
而不会出现一个关闭错误

由于
32%17==15==0x0f
,因此您期望的字节
'\x10'
从一开始就不在列表中

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

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

编辑2 经过一些挖掘,我可以说,至少会忽略
'\0'
处理backtick提供的输入。读取输入,直到显式跳过EOF和null字符


bash执行相同的操作,甚至有一个与事件关联的显式(即使已注释掉)。

dhke-您是正确的,但是off by one错误在另一侧-缺少一个条目。我怀疑这是由于通过管道发送chr(0)-它被丢弃。知道为什么吗?@sferic我甚至没有意识到
\0
也不见了,谢谢你提醒我。请参阅编辑。在设计的示例中,test.sh包含一行代码的解决方案是:
cat>/tmp/test.txt
。问题不在于
cat
的输出会发生分词(不是分词),而是空字节会过早终止字符串。Shell并不是设计用来处理任意二进制数据的。@chepner啊,没错,
=
不进行分词。这实际上让我更加确信,这只是一个你不能以任何方式依赖的未记录的副作用。
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")