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()
主.py
import config
import gameserver
gameServer = gameserver.GameserverHandler()
a = input()
gameServer.send_command('quitn')
大家好,我刚刚写了我的第一个python脚本。这个脚本只是在我的计算机上启动一个游戏服务器,在一个文件中写入stdout和stderr,并为我提供向服务器发送命令的选项。
但是有一个问题,当我使用send_command((时,游戏服务器不会得到stdin.write。我读到我必须在它后面放一个flush((。但这没有帮助。有趣的是,当我把代码改成这样时:
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()
我收到这个错误
Traceback (most recent call last): File "D:ProjektepythonPycharmProjectsServerLaunchermain.py", line 7, in <module>
gameServer.send_command('quit') File "D:ProjektepythonPycharmProjectsServerLaunchergameserver.py", line 22, in send_command
self.__gameServerInstance__.stdout.flush() AttributeError: 'NoneType' object has no attribute 'flush'
我认为这是因为我将stdout、stderr设置为一个文件,但为什么它比。
抱歉问了一个可能很愚蠢的问题,我刚刚开始python编程
Serge Ballesta回答后更新
更改了代码: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)
主.py
import config
import gameserver
import discord
gameServer = gameserver.GameserverHandler()
a = input()
print("SENDING")
gameServer.send_command('quitn')
print("FINISH")
a = input()
更改:
- stderr到子进程。标准输出
- 将文件操作更改为"wb">
- 在send_command中添加新行
但是的,不知道为什么,但这个过程仍然没有得到退出。当我把所有东西都放在main.py中并删除类时,就像这样。
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')
它起作用了,我不知道为什么,可能是stdin没有刷新吗?
以及快速答案的thx@Serge Ballesta
您的代码中存在许多不一致之处:
-
您对stdout和stderr使用相同的文件。这是错误的,可能会导致文件中的输出不正确。您应该使用特殊值
subprocess.STDOUT
:from subprocess import Popen, PIPE, STDOUT ... return Popen(config.bot_config[0]['GameServer']['Path'], stdin=PIPE, stdout=f, stderr=STDOUT)
-
您使用字节IO定义子进程,但以文本形式打开输出文件。您应该使用二进制模式:
f = open(config.bot_config[0]['GameServer']['OutPutFile'], "wb")
-
您发送一个命令
quit
。大多数CLI程序都希望命令以换行符终止。您应该在命令中添加一个n
:self.__gameServerInstance__.stdin.write(str.encode(command) + 'bn')
或
gameServer.send_command('quitn')
在这些修复之后,我可以成功地启动cmd.exe
子进程(在Windows上(,在exitn
命令之后终止它,并在输出文件中获得预期的数据。