[英]Why did python subprocess stdin.write() not work after a stdin.flush()?
游戲服務器.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()
主文件
import config
import gameserver
gameServer = gameserver.GameserverHandler()
a = input()
gameServer.send_command('quit\n')
大家好,我剛剛編寫了我的第一個 python 腳本。 該腳本只是在我的計算機上啟動一個游戲服務器,將標准輸出和標准錯誤寫入一個文件,並為我提供了向服務器發送命令的選項。
但是當我使用 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:\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'
我認為這是因為我將 stdout、stderr 設置為一個文件,但為什么它比它更有效。
抱歉問了一個愚蠢的問題,我剛開始 python 編程
更改代碼: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)
主文件
import config
import gameserver
import discord
gameServer = gameserver.GameserverHandler()
a = input()
print("SENDING")
gameServer.send_command('quit\n')
print("FINISH")
a = input()
變化:
但是,是的,不知道為什么,但過程仍然沒有退出。 當我將所有內容放入 main.py 並刪除 class 等時,就像這樣。
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')
它有效,我不知道為什么,可能是標准輸入沒有刷新?
並感謝@Serge Ballesta 的快速回答
您的代碼中有許多不一致之處:
您對 stdout 和 stderr 使用相同的文件。 這是錯誤的,可能會導致文件中的 output 不正確。 您應該使用特殊值subprocess.STDOUT
:
from subprocess import Popen, PIPE, STDOUT... return Popen(config.bot_config[0]['GameServer']['Path'], stdin=PIPE, stdout=f, stderr=STDOUT)
您使用字節 IO 定義子進程,但將 output 文件作為文本打開。 您應該使用二進制模式:
f = open(config.bot_config[0]['GameServer']['OutPutFile'], "wb")
你發送一個命令quit
。 大多數 CLI 程序都希望命令以換行符結束。 您應該在命令中添加一個\n
:
self.__gameServerInstance__.stdin.write(str.encode(command) + 'b\n')
或者
gameServer.send_command('quit\n')
在這些修復之后,我可以成功啟動cmd.exe
子進程(在 Windows 上),讓它在exit\n
命令后終止,並在 output 文件中獲得預期數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.