python脚本之间的正确连接 - stdin,stdout

时间:2017-05-31 15:07:07

标签: python

我想将图像(字符串格式的numpy.ndarray)发送到另一个脚本。第二个脚本用图像做一些事情并等待另一个图像。

第一个脚本有以下循环:

while True:
    out = os.fdopen(sys.stdout.fileno(), 'w')
    [here some code]
    img = cv2.imencode('.jpg', ndarray)[1].tostring()
    out.write(img)

第二个:

while True:
    data = sys.stdin.read()
    [here some code]

用法:

  

$ python script1.py | python script2.py

第一次迭代没问题。第二个脚本获取图像并做一些事情。然后是第二次迭代和以下错误:

out.write(img)
IOError: [Errno 9] Bad file descriptor
close failed in file object destructor:
IOError: [Errno 9] Bad file descriptor

然后第二个脚本中的data var为空。这段代码有什么问题? 如果我在循环上方有out = os.fdopen(sys.stdout.fileno(), 'w'),则在第二个脚本中,行data = sys.stdin.read()是无限的。

2 个答案:

答案 0 :(得分:1)

不是读取EOF,而是将长度作为单独的字段发送,并且只读取那么多字节。

在写作方面:

while True:
    # [here some code]
    img = cv2.imencode('.jpg', ndarray)[1].tostring()
    sys.stdout.write(str(len(img)) + '\n')
    sys.stdout.write(img)

在阅读方面,就个人而言,我建议使用发电机:

def inputStream():
    while True:
        header_line = sys.stdin.readline()
        if header_line == '': # file was closed on the input side
            raise StopIteration()
        len = int(header_line.strip())
        img = sys.stdin.read(len)
        yield img

for image in inputStream():
    pass # do something with "image" here

答案 1 :(得分:0)

错误

您正在查看这些错误,因为在第一个脚本(读取图像数据)中,正在循环中创建文件描述符。

它在第一次迭代中工作,但在循环的第二次迭代中,变量out引用的文件对象超出范围(被新文件对象替换),而文件对象是被破坏后,底层文件描述符将被关闭。

因此,新文件对象(第二次变量out已填充)不再是有效的文件描述符。

设计(可以帮助成为解决方案)

我假设使用2个单独脚本的原因(代码分为2个不同的模块)可能是:

  • 代码结构:然后我建议使用定义良好的模块,并在第一个(正在运行的应用程序)中导入处理器。因此,您不需要在不同进程之间传递信息并处理IO,可以使用函数调用和传递参数。

  • 多处理:如果你需要使用不同的脚本才能让多个进程协作,那么我建议使用标准库multiprocessing,它提供了良好的进程间通信机制,所以你赢了需要处理文件对象,描述符,stdout / stdin等。我会使用多处理Queue,第一个脚本填充队列(put),第二个脚本消耗(get