簡體   English   中英

為什么 python 子進程 stdin.write() 在 stdin.flush() 之后不起作用?

[英]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 編程

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)

主文件

import config
import gameserver
import discord

gameServer = gameserver.GameserverHandler()
a = input()
print("SENDING")
gameServer.send_command('quit\n')
print("FINISH")
a = input()

變化:

  • 標准錯誤到 subprocess.STDOUT
  • 將文件操作更改為“wb”
  • 向 send_command 添加新行

但是,是的,不知道為什么,但過程仍然沒有退出。 當我將所有內容放入 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 的快速回答

您的代碼中有許多不一致之處:

  1. 您對 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)
  2. 您使用字節 IO 定義子進程,但將 output 文件作為文本打開。 您應該使用二進制模式:

     f = open(config.bot_config[0]['GameServer']['OutPutFile'], "wb")
  3. 你發送一個命令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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM