简体   繁体   English

如何在进程stdin 仍在运行时写入进程stdin 并从其stdout 中读取?

[英]how can I write to a processes stdin and read from its stdout while it is still running?

Edit: I am running this on windows as the servers are administered on my main gaming rig编辑:我在 Windows 上运行它,因为服务器是在我的主要游戏装备上管理的

I am trying to create a minecraft server controller so that I can streamline the process of administering servers.我正在尝试创建一个 minecraft 服务器控制器,以便我可以简化管理服务器的过程。 I have been able to use subprocess to start and stop the server with no issues however when I try to get it to issue commands It will not.我已经能够使用子进程来启动和停止服务器而没有任何问题,但是当我尝试让它发出命令时它不会。 Unless I use subprocess.communicate() the problem with this solution however is that it causes the script to wait forever and eventually crash, leaving the server running.除非我使用subprocess.communicate()但是这个解决方案的问题是它导致脚本永远等待并最终崩溃,使服务器运行。 Here is the code for what I have.这是我所拥有的代码。

import subprocess


class Server:
    def __init__(self, server_start_bat, dir):
        self.server_start_bat = server_start_bat
        self.dir = dir

    def start_server(self):
        self.server = subprocess.Popen(self.server_start_bat, cwd=self.dir, shell=True, stdin=subprocess.PIPE,
                                       universal_newlines=True, text=True)

    def stop_server(self):
        self.run_command('stop')
        self.server.communicate()

    def op_me(self):
        self.run_command(f'op Username')

    def clear_weather(self):
        self.run_command(f'weather clear 1000000')

    def mob_griefing_on(self):
        self.run_command(f'gamerule mobGriefing True')

    def mob_griefing_off(self):
        self.run_command(f'gamerule mobGriefing True')

    def set_time_day(self):
        self.run_command(f'time set day')

    def set_time_night(self):
        self.run_command(f'time set night')

    def run_command(self, command_text):
        self.server.stdin.write(f'{command_text}\n')

Edit: Check out Non-blocking read on a subprocess.PIPE in python编辑: 在 python 中查看subprocess.PIPE 上的非阻塞读取

I was battling a very similar issue and it took me 3 days to get it all running.我正在与一个非常相似的问题作斗争,我花了 3 天的时间才让它全部运行。 The problem with subprocess.communicate is that you can only call it once, and the output seems to be given only once the subprocess terminates (in the experience i had, could very well be wrong). subprocess.communicate 的问题是你只能调用它一次,并且输出似乎只在子进程终止时给出(根据我的经验,很可能是错误的)。

The question i had, which your question imho boils down to was: how can I write to a processes stdin and read from its stdout while it is still running?我的问题,你的问题恕我直言归结为:我如何写入进程标准输入并在它仍在运行时从它的标准输出中读取?

I ended up using Pipes.我最终使用了管道。 Note that they have to me flushed if you write something that is smaller that BUFSIZE, which is 0x1000 in my case.请注意,如果您编写的内容小于 BUFSIZE(在我的情况下为 0x1000),则它们必须刷新。 See man pipe for more info.有关更多信息,请参阅man pipe

Anyway, below is my code.无论如何,下面是我的代码。

import time
import pty
import os
import subprocess
PIPE_BUFSIZE = 4096
_control = False


class Pipe:

    def __init__(self, flags=None, terminal=True):
        """Creates a Pipe you can easily write to and read from. Default is to open up a pseudo-terminal.
            If you supply flags, pipe2 is used."""

        if flags or not terminal:
            self._readfd, self._writefd = os.pipe2(flags)
        else:   # default
            self._readfd, self._writefd = pty.openpty()

        self.readobj = open(self._readfd, "rb", 0)  
        self.writeobj = open(self._writefd, "wb", 0)

    def write(self, text):
        if isinstance(text, str):
            text = text.encode()

        result = self.writeobj.write(text)
        self.writeobj.flush()
        return result

    def read(self, n):
        if _control:    # im not using this anymore since the flush seems to be reliable
            controlstr = b"this_was_flushed"
            controllen = len(controlstr)

            self.writeobj.write(controlstr)
            time.sleep(.001)
            self.writeobj.flush()

            result = self.readobj.read(n+controllen)
            assert result[-controllen:] == controlstr
            return result[:-controllen]
        else:
            self.writeobj.flush()
            return self.readobj.read(n)


class ProcessIOWrapper:
    """Provides an easy way to redirect stdout and stderr using pipes. Write to the processes STDIN and read from STDOUT at any time! """

    def __init__(self, args, inittext=None, redirect=True):

        #create three pseudo terminals
        self.in_pipe = Pipe()
        self.out_pipe = Pipe()
        self.err_pipe = Pipe()

        # if we want to redirect, tell the subprocess to write to our pipe, else it will print to normal stdout
        if redirect:
            stdout_arg= self.out_pipe.writeobj
            stderr_arg= self.err_pipe.writeobj
        else:
            stdout_arg=None
            stderr_arg= None

        self.process = subprocess.Popen(args, stdin=self.in_pipe.readobj, stdout=stdout_arg, stderr=stderr_arg)


    def write(self, text):
        return self.in_pipe.write(text)

    def read(self, n, start=None):
        return self.out_pipe.read(n)




Small C Program i used for testing (used others, too)我用于测试的小 C 程序(也使用过其他程序)

#include <stdio.h>


int main(){
    puts("start\n");
    char buf[100]="bufbufbuf";
    while(1){

        gets(buf);
        for (int i=0; i<strlen(buf); i++)
            if (i%2==0) buf[i]+=1;

        puts(buf);
    }
}


声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何运行只能写入STDOUT并从STDIN读取的脚本? - How to run a script that can only write to STDOUT and read from STDIN? python asyncio如何读取StdIn并写入StdOut? - python asyncio how to read StdIn and write to StdOut? Python - 如何从 shell 读取标准输入,并将标准输出发送到 shell 和文件 - Python - how can I read stdin from shell, and send stdout to shell and file 在python中长时间运行的子进程上写入stdin并从stdout读取 - write to stdin and read from stdout on long-running child process in python 在孩子还活着时如何从其标准品中读取 - How to read from child's stdout while it still alive 重复写入stdin并从python中读取进程的stdout - Repeatedly write to stdin and read from stdout of a process from python 如何在 python 中广泛和/或交替地从 stdout 和/或 stderr 读取并写入进程的 stdin? - How to wildly and/or alternatingly read from stdout and/or stderr and write to stdin of a process in python? 子进程,从 STDOUT 读取时重复写入 STDIN (Windows) - Subprocess, repeatedly write to STDIN while reading from STDOUT (Windows) 如何执行命令并读取/写入其 STDIN/TTY(一起)? - How to execute a command and read/write to its STDIN/TTY (together)? 如何判断非阻塞stdin的读取量? - How can I tell how much to read from nonblocking stdin?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM