简体   繁体   中英

Supply stdin input to subprocess.Popen() after execution of the process had begun ( and before it had finished )

I'm making a program with a remote shell utility in Python3, using sockets and subprocess. Everything works perfectly so far but i have encountered an issue i can't find the solution for. Here is the code on my server script which executes a command received from the client:

process = subprocess.Popen(client_buffer.decode('utf-8').split(), stdout = subprocess.PIPE) # Creating a process
        while True: # Reading and sending the stdout from the process in realtime
            shell_output = process.stdout.readline() # Read a line from stdout
            return_code = process.poll()
            print(shell_output)
            print(return_code)
            if shell_output.decode('utf-8') == '' and return_code is not None: 
                #print("Process execution complete. Sending user prefix")
                send(client, ("<#" + color.user + getpass.getuser() + color.endc + "@" + color.dir + cwd() + color.endc + ">").encode('utf-8'))
                break
            elif shell_output: 
                # Process execution incomplete, signaling to client with code 2
                send(client, int_to_bytes(2))
                # And sending the next line of stdout
                send(client, shell_output)

All works well and i was satisfied, but there is one limitation that i can't figure out how to remove. Namely, i can easily supply the server with a command with arguments and the server will execute it and send the output back, that works well, but if the program started by the command asks for additional input (for example a "(y/n)" question) before the execution of the process is over (mid-execution), i do not know how to supply the input to the process.

Can i do this with subprocess.Popen()? Any clue will be helpful and i thank You in advance. I forgot to add, the program is meant to be used in Linux.

PS Any functions and variables of which definitions/declarations i haven't provided in the code sample are irrelevant, but the project can be found on my github incase anyone wants to see more of the code

First I think readline() is problematic here, unless the prompt from the program ends in a newline(): the program writes a prompt and is waiting for an answer while readline() is waiting for an end-of-line. I think you're going to have to use read() instead and do things a bit more low level.

To actually send something to the program, I think you can just write to process.stdin .

Have a look at pexpect ( https://pexpect.readthedocs.io ). I'm not sure it fits your use case, but if it does it can make life easier so it's worth the effort to find out.

One other thing to consider: many commands have an option to make it work without extra prompts, to prevent the problem you're having when run from another program. If that's the case with the program you're using, that would be by far the easiest solution.

By providing the stdin arg, you can access the subprocess'd processes' stdin

p = subprocess.Popen(
    ...
    stdin=subprocess.PIPE,
    ...
)

p.stdin.write("foo")

You can also just send the input to myprocess.communicate() , but it will then block until completion!

...
stdout, stderr = p.communicate(myinput)

You can send a large amount of inputs to answer many questions if you know what they will be in advance (such as a friendly "y\n" * 100 )

Well, first of all obvious and trivial mistake:

shell_output = process.stdout.readline()

NO.!! You can only write to the standard input and read from the standard input.

stdout = standard output
stdin = standard input

View piping as real pipes. The output flows in the input of the other command.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM