Login without Python subsystem with permanent logout on Windows
I am trying to run a command with subproccess and _thread modules. The subprocess has an output stream. To combat this, I used two threads, one constantly printing newlines and the other checking the input. When I pass the input to the subprocess through proc.stdin.write('Some string')
, it returns 1 and then I don't get the output. The communication doesn't work for most of the other questions I've read because it blocks waiting for EOF even though it prints the first line of what will be returned. I've seen several solutions using "pty", but it is not supported on Windows.
The file in the server folder is only minecraft server if you want to try it yourself.
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
source to share
proc.communicate()
is waiting for the subprocess to finish, so it can be used at most once - you can pass all the input at once and get all the output after the child finishes.
Unless you are modifying the I / O, you do not need to redirect the subprocess' stdin / stdout.
To feed input to a subprocess on a background thread, and to print its output as soon as it arrives in turn:
#!/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='')
Note about p.stdin
:
-
print()
adds a new line at the end of eachline
. This is needed because itinput()
splits a newline -
p.stdin.flush()
called after each line (line_buffering=True
)
The output of a minecraft file may be delayed until its stdout buffer is flushed.
If you have nothing to add around "do something with comments line
here", do not redirect the appropriate channels (ignoring character encoding issues for a moment).
TextIOWrapper
uses the default universal newline mode. Specify the parameter newline
explicitly if you don't want to.
source to share