我正在尝试使用subproccess和_thread模块运行命令.子进程有一个输出流.为了解决这个问题,我使用了两个线程,一个不断打印新线,另一个是检查输入.当我通过proc.stdin.write(‘Some string’)传递子进程输入时,它返回1然后我没有输出.沟通不能像我读过的大多数其他问题一样工作,因为它会阻止等待EOF,尽管它确实打印了将要返回的任何内容的第一行.我看到了一些使用’pty’的解决方案,但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,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
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",cwd=r'C:\Users\Derek\Desktop\server',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的注意事项:
> print()在每行的末尾添加换行符.这是必要的,因为input()剥离换行符
>每行后调用p.stdin.flush()(line_buffering = True)
Minecraft的输出可能会被延迟,直到其stdout缓冲区被刷新.
如果你没有什么可以添加“在这里做一些事情”评论,那么不要重定向相应的管道(暂时忽略字符编码问题).
TextIOWrapper默认使用通用换行模式.如果您不想要,请明确指定换行参数.