Search code examples
python-3.xsubprocesspipe

subprocess.Popen - read output keeping session open


I need to setup a session with subprocess.Popen ,

then I need to run a command1 that gives me an output1

then I need to use output1 as a parameter to run command2

IMPORTANT > command1 creates a session, so I cant close the pipe between command1 and command2.

how do I read the output of this pipe while it's still open?

I have found in other questions something like this. It only "almost" works tho.

bash_session = subprocess.Popen(['bash'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
bash_session.stdin.write(f"command1  \n".encode())
bash_session.stdin.flush()
output_lines = []
while True:
    line = bash_session.stdout.readline().decode().strip()
    if not line:  #NOT WORKING!*** 
        #- however if I press CTRL+C at the REPL after waiting long enough, the rest of the loop fills output_lines as expected
        break
    output_lines.append(line)

bash_session.stdin.write(f"command1 {output_lines[len(output_lines)-1]}\n".encode())

Solution

  • This worked for me (added a few more line of code just to show a more generic scenario):

    import subprocess
    
    bash_session = subprocess.Popen(['bash'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    bash_session.stdin.write(f"command1  \n".encode())
    bash_session.stdin.write(f"command2  \n".encode())
    bash_session.stdin.write(f"command3; echo BASH_SESSION_LEFT_OPEN_FOR_FUTURE_COMMANDS\n".encode())
    bash_session.stdin.flush()
    output_lines = []
    for line in iter(bash_session.stdout.readline,  b'BASH_SESSION_LEFT_OPEN_FOR_FUTURE_COMMANDS\n'):
        output_lines.append(line.decode().strip())
        print ("stdout:", line.decode().strip())
    
    bash_session.stdin.write(f"command4 {output_lines[len(output_lines)-1]}\n".encode())
    

    all I did was changing the while to a for loop, using iter() with a sentinel value set to a custom string. This helps me stopping reading lines just before I get hanged to the open pipe.

    If anyone has a more elegant solution please let me know, in the meantime, this seems to get the job done :)