Python 在 Windows 上具有恒定输出的无块子进程输入
Python blockless subproccess input with constant output on Windows
我正在尝试 运行 带有子进程和 _thread 模块的命令。子进程有一个输出流。为了解决这个问题,我使用了两个线程,一个不断地打印新行,另一个正在检查输入。当我通过 proc.stdin.write('Some string')
传递子进程输入时 returns 1 然后我没有输出。根据我读过的大多数其他问题,通信不起作用,因为它阻止等待 EOF,尽管它确实打印了将要返回的内容的第一行。我看到一些使用 'pty' 的解决方案,但 Windows.
不支持它
server文件夹里的文件只是一个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
proc.communicate()
等待子进程完成因此最多可以使用 一次 – 你可以传递 all 输入立即获取子进程退出后的所有输出。
如果您不修改 input/output 那么您不需要重定向子进程' 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
的注意事项:
print()
在每个 line
的末尾添加一个换行符。这是必要的,因为 input()
去掉换行符
p.stdin.flush()
在每行 (line_buffering=True
) 之后被调用
Minecraft 的输出可能会延迟,直到其标准输出缓冲区被刷新。
如果您在 "do something with line
here" 评论周围没有什么可添加的,那么请不要重定向相应的管道(暂时忽略字符编码问题)。
TextIOWrapper
默认使用通用换行模式。如果不需要,请明确指定 newline
参数。
我正在尝试 运行 带有子进程和 _thread 模块的命令。子进程有一个输出流。为了解决这个问题,我使用了两个线程,一个不断地打印新行,另一个正在检查输入。当我通过 proc.stdin.write('Some string')
传递子进程输入时 returns 1 然后我没有输出。根据我读过的大多数其他问题,通信不起作用,因为它阻止等待 EOF,尽管它确实打印了将要返回的内容的第一行。我看到一些使用 'pty' 的解决方案,但 Windows.
server文件夹里的文件只是一个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
proc.communicate()
等待子进程完成因此最多可以使用 一次 – 你可以传递 all 输入立即获取子进程退出后的所有输出。
如果您不修改 input/output 那么您不需要重定向子进程' 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
的注意事项:
print()
在每个line
的末尾添加一个换行符。这是必要的,因为input()
去掉换行符p.stdin.flush()
在每行 (line_buffering=True
) 之后被调用
Minecraft 的输出可能会延迟,直到其标准输出缓冲区被刷新。
如果您在 "do something with line
here" 评论周围没有什么可添加的,那么请不要重定向相应的管道(暂时忽略字符编码问题)。
TextIOWrapper
默认使用通用换行模式。如果不需要,请明确指定 newline
参数。