简体   繁体   English

我如何将 stream 输入到 python Popen 子进程和 stream Z78E6221F6393D1356681DB93 中?

[英]How can I stream input into a python Popen subprocess and stream output from it?

I'm attempting to basically create a shell in python using subprocess.Popen .我正在尝试使用 subprocess.Popen 在 python 中创建一个subprocess.Popen As boilerplate code for testing purposes, this is what I have:作为用于测试目的的样板代码,这就是我所拥有的:

if __name__ == '__main__':
    ps = subprocess.Popen(
        input('command? '),
        shell=True,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True
    )

    print(ps.stdout.read())
    time.sleep(1) # provide enough time to register completion if the command is a one-off, like dir or echo
    while ps.poll() == None: # ps.poll() returns None if still running
        try:
            # method one
            ps.stdin.write(input())
            ps.communicate()
            print(ps.stdout.read())

            # method two
            ps.stdin.write(input())
            print(ps.communicate()[0])

            # method three
            print(ps.communicate(input())[0])
        except:
            continue

    print('Process Finished')

Each method is a different (failed) attempt.每种方法都是不同的(失败的)尝试。

For commands like python which should open the python CLI interpreter, this completely fails.对于像python这样应该打开 python CLI 解释器的命令,这完全失败了。 However, for one-off commands like dir or ls or even running python -c "<some python>" it works just fine.但是,对于dirls之类的一次性命令,甚至运行python -c "<some python>"它都可以正常工作。

CLI log:命令行日志:

C:\Users\nj2u2\Desktop\test>python test.py
command? echo hello
hello

Process Finished

C:\Users\nj2u2\Desktop\test>python test.py
command? dir
 Volume in drive C has no label.
 Volume Serial Number is D6B7-6B8D

 Directory of C:\Users\nj2u2\Desktop\test

07/03/2020  12:26 AM    <DIR>          .
07/03/2020  12:26 AM    <DIR>          ..
07/03/2020  08:20 PM             6,811 subprocess_plus.py
07/04/2020  12:55 PM               580 test.py
07/03/2020  08:25 PM    <DIR>          __pycache__
               2 File(s)          7,391 bytes
               3 Dir(s)  1,487,446,302,720 bytes free

Process Finished

C:\Users\nj2u2\Desktop\test>python test.py
command? python


After that last command, python , it just hangs at print(ps.stdout.read()) .在最后一个命令python之后,它只是挂在print(ps.stdout.read())处。

I'd like to know why it's hanging, and how I can fix it.我想知道它为什么挂起,以及如何修复它。

The communicate method can only be used for non interactive commands because it sends a one shot input and then waits for the sub process to terminate. communicate方法只能用于非交互式命令,因为它发送一个单次输入,然后等待子进程终止。 That is the reason that it can only work with what you call one-off commands.这就是它只能与您所谓的一次性命令一起使用的原因。

But beware, pipes do not support the terminal discipline in which a read call automatically flushes the output, and where a new line causes a read to return immediately.但请注意,管道不支持终端规则,其中读取调用会自动刷新 output,并且新行会导致读取立即返回。 So nothing guarantees that you can use that to provide interactive IO to the python CLI interpretor.因此,没有任何东西可以保证您可以使用它为 python CLI 解释器提供交互式 IO。 Pipes are just streams, and can be buffered so you can just be sure that all the input will be delivered, and that when the output channels will be closed (ie when the sub-process command will terminate) you will receive all the output.管道只是流,并且可以被缓冲,因此您可以确保所有输入都将被传递,并且当 output 通道将关闭时(即当子进程命令终止时)您将收到所有 output。 The way input and output are intermixed depends on the way the sub-process command is programmed.输入和output混用的方式取决于子流程指令的编程方式。 If it willingly flushes its output before reading, and you do the same in your code, then interactive processing is possible, but if it does not, there is no way to expect to receive something after each end of line.如果它愿意在读取之前刷新其 output,并且您在代码中执行相同操作,则可以进行交互式处理,但如果不这样做,则无法期望在每行结束后收到某些内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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