Python 3.x python popen,stdout显示在strace中,但不显示在popen.stdout.read()中

Python 3.x python popen,stdout显示在strace中,但不显示在popen.stdout.read()中,python-3.x,popen,blocking,Python 3.x,Popen,Blocking,我使用下面的python脚本,试图从没有适当换行符的程序中读取。这允许读取,而无需担心阻塞读取。然而,由于我对线程了解不够,我怀疑这就是我的问题所在 import subprocess import shlex import os import time from threading import Thread import queue class NonBlockingStreamReader: def __init__(self, stream): """

我使用下面的python脚本,试图从没有适当换行符的程序中读取。这允许读取,而无需担心阻塞读取。然而,由于我对线程了解不够,我怀疑这就是我的问题所在

import subprocess
import shlex
import os
import time
from threading import Thread
import queue


class NonBlockingStreamReader:
    def __init__(self, stream):
        """
        :param stream: the stream to read from.  Usually stdout or stderr.
        """
        self._s = stream
        self._q = queue.Queue()

        def _populate_queue(_stream, _queue):
            """Collect lines from 'stream' and put them in 'queue'"""
            while True:
                _char = _stream.read(1)
                if _char:
                    _queue.put(_char)
                else:
                    raise UnexpectedEndOfStream

        self._t = Thread(
            target=_populate_queue,
            args=(
                self._s,
                self._q
            )
        )
        self._t.daemon = True
        self._t.start() # Start collecting characters from the stream

    def readchar(self, timeout=None):
        try:
            _tmp = self._q.get(block=timeout is not None, timeout=timeout)
            return _tmp
        except queue.Empty:
            return None


class UnexpectedEndOfStream(Exception):
    pass


def main():
    proc = subprocess.Popen(
        shlex.split('strace -o /home/arts/dlm/trace_output.txt stdbuf -o0 /home/arts/dlm/test'),
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )

    nbsr = NonBlockingStreamReader(proc.stdout)

    _data = b''
    while True:
        _char = nbsr.readchar(0.1)
        if not _char:
            break
        else:
            _data += _char
    print(_data.decode())

    proc.stdin.write(b'12345\n')

    _data = b''
    while True:
        _char = nbsr.readchar(5)
        if not _char:
            break
        else:
            _data += _char
    print(_data.decode())
    print('Annnnd done.')


if __name__ == '__main__':
    main()
以下是
测试
程序的预期输出:

Line 1 test
Line 2 test
Line 3 input: 12345      <--- input from user
Line 4 test: 12345
这表明(至少对我来说)应用程序正在提供请求的输出
read(0,“12345\n”,4096)
显示
proc.stdin.write(b'12345\n')
,除非我遗漏了什么。下一行显示它读取我期望的输出。然而,实际产出是:

Line 1 test
Line 2 test
Line 3 input:

Annnnd done.
如果我在
\u char=\u stream.read(1)
之后放置一些print语句,它将不显示任何内容。如果我将它们添加到
readchar
函数中,则会显示
None


有东西打破了标准,所以不管它去哪里,它都不会进入管道。有人能指引我正确的方向吗?

找到了。需要
bufsize=0
作为参数,以
Popen

解决第二次读取循环中的两个问题:

  • 它是在空的
    \u data
    而不是
    \u char
    上断开的,并且
    \u data
    在循环的顶部被设置为
    b'
    ,因此它总是在不向
    \u data
    写入任何内容的情况下退出
  • 当读卡器的缓冲区为空时,它就会中断,这可能是在写入或读取子进程的整个输出之后,也可能不是,这取决于所涉及的进程和线程的计时

您可能希望在读卡器中设置EOF标志,而不是在读卡器中提升
unexpectedDofstream
,然后将循环基于该标志(或者更确切地说,基于设置该标志且队列为空的派生条件)。

谢谢!是的,我也注意到了这一点,并且应该在我的自我回答中提供这一点,但唉,我没有!因此,你得到了正确的答案。另外,关于EOF捕获的好主意。
Line 1 test
Line 2 test
Line 3 input:

Annnnd done.