Reputation: 1
gameserver.py
import config
import os
from subprocess import Popen, PIPE, STDOUT
class GameserverHandler:
def __init__(self):
print("==== Gameserver ====")
self.__gameServerInstance__ = self.restart_gameserver()
print("\tGameserver started")
def restart_gameserver(self):
if os.path.exists(config.bot_config[0]['GameServer']['OutPutFile']):
os.remove(config.bot_config[0]['GameServer']['OutPutFile'])
f = open(config.bot_config[0]['GameServer']['OutPutFile'], "wb")
return Popen(config.bot_config[0]['GameServer']['Path'], stdin=PIPE, stdout=f, stderr=STDOUT)
def send_command(self, command):
try:
self.__gameServerInstance__.stdin.write(str.encode(command))
self.__gameServerInstance__.stdin.flush()
except BrokenPipeError:
pass
except OSError as e:
exit()
main.py
import config
import gameserver
gameServer = gameserver.GameserverHandler()
a = input()
gameServer.send_command('quit\n')
Hallo everyone, i just wrote my first python script. This script just starts a gameserver on my computer, write the stdout and stderr in a file and gives me an option to send commands to the server.
But there is the Problem when i use send_command() the gameserver dont gets the stdin.write. I read that i have to put a flush() after it. But this is not helping. Funny is when i change the code to this:
def send_command(self, command):
try:
self.__gameServerInstance__.stdin.write(str.encode(command))
self.__gameServerInstance__.stdin.flush()
self.__gameServerInstance__.stdout.flush()
self.__gameServerInstance__.stderr.flush()
except BrokenPipeError:
pass
except OSError as e:
exit()
I get this Error
Traceback (most recent call last): File "D:\Projekte\python\PycharmProjects\ServerLauncher\main.py", line 7, in <module>
gameServer.send_command('quit') File "D:\Projekte\python\PycharmProjects\ServerLauncher\gameserver.py", line 22, in send_command
self.__gameServerInstance__.stdout.flush() AttributeError: 'NoneType' object has no attribute 'flush'
I think its because i set the stdout, stderr to a file, but why is it working than.
Sorry for a maybe dumb question, i'm just started python programming
Changed the code: gameserver.py
def restart_gameserver(self):
if os.path.exists(config.bot_config[0]['GameServer']['OutPutFile']):
os.remove(config.bot_config[0]['GameServer']['OutPutFile'])
f = open(config.bot_config[0]['GameServer']['OutPutFile'], "wb")
return Popen(config.bot_config[0]['GameServer']['Path'], stdin=PIPE, stdout=f, stderr=STDOUT)
main.py
import config
import gameserver
import discord
gameServer = gameserver.GameserverHandler()
a = input()
print("SENDING")
gameServer.send_command('quit\n')
print("FINISH")
a = input()
Changes:
But yeah dont know why but still the process dont get the quit. When i put everything in the main.py and remove the class and so like this.
if os.path.exists(config.bot_config[0]['GameServer']['OutPutFile']):
os.remove(config.bot_config[0]['GameServer']['OutPutFile'])
f = open(config.bot_config[0]['GameServer']['OutPutFile'], "wb")
p = Popen(config.bot_config[0]['GameServer']['Path'], stdin=PIPE, stdout=f, stderr=STDOUT)
a = input()
p.stdin.write(b'quit')
it works, i dont know why, could it be that the stdin is not flushing?
And thx for the fast answer @Serge Ballesta
Upvotes: 0
Views: 686
Reputation: 148880
There are a number of inconsistencies in your code:
you use the same file for both stdout and stderr. That is wrong and may lead to incorrect output in the file. You should use the special value subprocess.STDOUT
:
from subprocess import Popen, PIPE, STDOUT
...
return Popen(config.bot_config[0]['GameServer']['Path'], stdin=PIPE,
stdout=f, stderr=STDOUT)
You define the child process with bytes IO, yet open the output file as text. You should use binary mode:
f = open(config.bot_config[0]['GameServer']['OutPutFile'], "wb")
You send a command quit
. Most CLI programs expect a command to be terminated with a newline character. You should add a \n
to your command:
self.__gameServerInstance__.stdin.write(str.encode(command) + 'b\n')
or
gameServer.send_command('quit\n')
After those fixes, I could successfully start a cmd.exe
child process (on Windows), have it to terminate after the exit\n
command, and got the expected data in the output file.
Upvotes: 1