在Windows上使用恒定输出的Python无块subprocessinput

我正在尝试运行与subprocess和_thread模块的命令。 subprocess有一个输出stream。 为了解决这个问题,我使用了两个线程,一个是不断打印新行,另一个是检查input。 当我通过proc.stdin.write('Some string')的subprocessinput,它返回1,然后我得不到输出。 沟通不能按照我读过的大多数其他问题工作,因为它阻止了等待EOF,尽pipe它打印了要返回的东西的第一行。 我看到一些使用“pty”的解决scheme,但在Windows上不支持。

服务器文件夹中的文件只是一个Minecraft服务器,如果你想自己尝试。

 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 

Solutions Collecting From Web of "在Windows上使用恒定输出的Python无块subprocessinput"

proc.communicate()等待子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注意p.stdin

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

minecraft的输出可能会延迟,直到其stdout缓冲区被刷新。

如果在“在这里执行某些操作”注释中没有添加任何内容,请不要重定向相应的管道(忽略字符编码问题)。

TextIOWrapper默认使用通用换行符模式。 如果你不需要,明确指定newline参数。