How to create non-blocking continuous reading from `stdin`?

前端 未结 5 1601
小蘑菇
小蘑菇 2021-02-04 19:27

I have a single process, which has been created like this:

p = subprocess.Popen(args   = \'./myapp\',
                     stdin  = subprocess.PIPE,
                     


        
5条回答
  •  无人及你
    2021-02-04 19:49

    I think you are maybe just not seeing the output of what is going on. Here's a complete example that seems to work on my box, unless I'm completely misunderstanding what you want. The main change I made is setting stdout for p to sys.stdout instead of subprocess.PIPE. Maybe I'm misunderstanding the thrust of your question and that bit is crucial...

    Here's the full code and output:

    In the sending (testing) process (I named it test_comms.py). I'm on Windows currently, so excuse the .bat:

    import time
    import subprocess
    import sys
    
    # Note I'm sending stdout to sys.stdout for observation purposes
    p = subprocess.Popen(args = 'myapp.bat',
                         stdin  = subprocess.PIPE,
                         stdout = sys.stdout,
                         universal_newlines=True)
    
    #Send 10 messages to the process's stdin, 1 second apart                    
    for i in range(10):
        time.sleep(1)
        p.stdin.write('my message\n')
    

    myapp.bat is trivially:

    echo "In the bat cave (script)"
    python myapp.py
    

    myapp.py contains (using Queue rather than queue - current environment Python 2):

    import Queue
    from Queue import Empty
    import threading
    import sys
    import time
    
    def get_input():
        print("Started the listening thread")
        for line in iter(sys.stdin.readline, ''):
            print("line arrived to put on the queue\n")
            q.put(line)
        sys.stdin.close()
    
    print("Hi, I'm here via popen")    
    q = Queue.Queue()
    
    threading.Thread(name   = 'input-getter',
                     target = get_input).start()
    
    print("stdin listener Thread created and started")
    
    # Read off the queue - note it's being filled asynchronously based on 
    # When it receives messages.  I set the read interval below to 2 seconds
    # to illustrate the queue filling and emptying.
    while True:
        time.sleep(2)
        try:
            print('Queue size is',q.qsize())
            print('input:', q.get_nowait())
        except Empty:
            print('no input')
    
    print("Past my end of code...")
    

    Output:

    D:\>comms_test.py
    
    D:\>echo "In the bat cave (script)"
    "In the bat cave (script)"
    
    D:\>python myapp.py
    Hi, I'm here via popen
    Started the listening threadstdin listener Thread created and started
    
    line arrived to put on the queue
    
    line arrived to put on the queue
    
    ('Queue size is', 2)
    ('input:', 'my message\n')
    line arrived to put on the queue
    
    line arrived to put on the queue
    
    ('Queue size is', 3)
    ('input:', 'my message\n')
    line arrived to put on the queue
    
    line arrived to put on the queue
    
    ('Queue size is', 4)
    ('input:', 'my message\n')
    line arrived to put on the queue
    
    line arrived to put on the queue
    
    ('Queue size is', 5)
    ('input:', 'my message\n')
    line arrived to put on the queue
    
    line arrived to put on the queue
    
    
    D:\>('Queue size is', 6)
    ('input:', 'my message\n')
    ('Queue size is', 5)
    ('input:', 'my message\n')
    ('Queue size is', 4)
    ('input:', 'my message\n')
    ('Queue size is', 3)
    ('input:', 'my message\n')
    ('Queue size is', 2)
    ('input:', 'my message\n')
    ('Queue size is', 1)
    ('input:', 'my message\n')
    ('Queue size is', 0)
    no input
    ('Queue size is', 0)
    no input
    ('Queue size is', 0)
    no input
    

提交回复
热议问题