Windows上具有恒定输出的Python无块子过程输入

发布于 2021-01-29 14:59:10

我正在尝试使用subproc和_thread模块运行命令。子过程具有输出流。为了解决这个问题,我使用了两个线程,一个不断地打印新行,另一个正在检查输入。当我通过子过程输入时,proc.stdin.write('Some string')它返回1,然后没有任何输出。交流不会像我读过的大多数其他问题一样起作用,因为它会阻止等待EOF,尽管它确实会打印要返回的内容的第一行。我看到了一些使用“
pty”的解决方案,但Windows不支持它。

如果您想自己尝试,则服务器文件夹中的文件只是我的世界服务器。

from subprocess import Popen,PIPE
import _thread
import sys
# asdf
proc = None
run = True
stdout = None
stdin = None


def getInput():
    global proc
    global run, stdin, stdout
    print("Proc inside the get input funct"+str(proc))
    inputs = input("Enter Something" + "\n")
    print("YOU ENTERED:", inputs)
    print("ATTEMPTING TO PIPE IT INTO THE CMD")
    run = True

    """----------------------------------------"""
    """        Works but blocks outputs        """
    """----------------------------------------"""
    # out,err=proc.communicate(bytes(inputs,'UTF-8'))
    # proc.stdin.flush()
    # print("Out is: "+out)




    """----------------------------------------"""
    """   Doesn't write but doesn't block      """
    """----------------------------------------"""
    # test = 0
    # test=proc.stdin.write(bytes(inputs,'UTF-8'))
    # print(test)
    # proc.stdin.flush()


def execute(command):
    global proc, stdin, stdout
    proc = Popen(command, cwd='C://Users//Derek//Desktop//server//',stdin=PIPE,stdout=PIPE,stderr=stdout, shell=True)
    lines_iterator = iter(proc.stdout.readline, "")
    print("Proc inside of the execute funct:"+str(proc))
    # print(lines_iterator)
    for line in lines_iterator:
        # print(str(line[2:-1]))
        # if line.decode('UTF-8') != '':
        print(line[:-2].decode('UTF-8')),  # yield line
        sys.stdout.flush()


threadTwo = _thread.start_new_thread(execute, (["java", "-jar", "minecraft_server.jar"], ))

while 1:
    if run and proc!=None:
        run = False
        threadOne = _thread.start_new_thread(getInput, ( ))

    pass
关注者
0
被浏览
106
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    proc.communicate()等待子进程完成,因此最多只能使用 一次 –您可以 一次 传递 所有 输入,并在子进程退出后获取所有输出。

    如果不修改输入/输出,则无需重定向子流程的stdin / stdout。

    要将输入馈送到后台线程中的子流程,并在一行一行到达时立即打印其输出:

    #!/usr/bin/env python3
    import errno
    from io import TextIOWrapper
    from subprocess import Popen, PIPE
    from threading import Thread
    
    def feed(pipe):
        while True:
            try: # get input
                line = input('Enter input for minecraft')
            except EOFError:
                break # no more input
            else:
                # ... do something with `line` here
    
                # feed input to pipe
                try:
                    print(line, file=pipe)
                except BrokenPipeError:
                    break # can't write to pipe anymore
                except OSError as e:
                    if e.errno == errno.EINVAL:
                        break  # same as EPIPE on Windows
                    else:
                        raise # allow the error to propagate
    
        try:
            pipe.close() # inform subprocess -- no more input
        except OSError:
            pass # ignore
    
    with Popen(["java", "-jar", "minecraft_server.jar"],
               cwd=r'C:\Users\Derek\Desktop\server',
               stdin=PIPE, stdout=PIPE, bufsize=1) as p, \
         TextIOWrapper(p.stdin, encoding='utf-8', 
                       write_through=True, line_buffering=True) as text_input:
        Thread(target=feed, args=[text_input], daemon=True).start()
        for line in TextIOWrapper(p.stdout, encoding='utf-8'):
            # ... do something with `line` here
            print(line, end='')
    

    注意事项p.stdin

    1. print()在每个末尾添加一个换行符line。这是必要的,因为input()剥离换行符
    2. p.stdin.flush()每行(line_buffering=True)之后被调用

    我的世界的输出可能会延迟到刷新其标准输出缓冲区。

    如果您在 _“line在此处执行某些操作”_注释周围没有可添加的内容,请不要重定向相应的管道(暂时忽略字符编码问题)。

    TextIOWrapper默认情况下使用通用换行模式。newline如果不想,请明确指定参数。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看