subprocess timeout/wait与time.sleep失效问题求助
解决time.sleep()与popen.wait()和Minecraft服务器交互异常问题
核心问题1:stdin缓冲区未刷新,导致命令延迟批量发送
你向Minecraft服务器进程的stdin写入命令时,Python会默认缓冲这些数据,不会立刻传递给服务器。哪怕你加了time.sleep(),之前的命令都堆在缓冲区里,直到后续操作触发缓冲区刷新,才会一次性发送,看起来就像所有命令同时执行了。
解决方案:每次写入后强制刷新缓冲区
还要注意原代码里漏了time模块的导入,必须补上。修正后的代码如下:
import subprocess import time from subprocess import Popen, PIPE MCser = subprocess.Popen(["java.exe", "-Xms8024M", "-Xmx10096M", "-jar", "quilt-server-launch.jar"], stdout = PIPE, stdin = PIPE, stderr = PIPE) MCser.stdin.write(b'say test\n') MCser.stdin.flush() # 强制刷新缓冲区,立刻发送命令 MCser.stdin.write(b'say Restart after 30s\n') MCser.stdin.flush() time.sleep(20) MCser.stdin.write(b'say Restart after 10s\n') MCser.stdin.flush() time.sleep(10) MCser.stdin.write(b'stop\n') MCser.stdin.flush()
核心问题2:Popen.wait()用法完全错误
Popen.wait(timeout)的作用是等待进程终止,超时后抛出异常。但Minecraft服务器启动后会持续运行,不会自动终止,所以第一次wait(30)超时后执行写入,后续的wait(20)还是在等同一个运行中的进程,会立刻超时触发写入,导致所有命令瞬间执行。
正确做法:用time.sleep()控制时间间隔,配合缓冲区刷新
不需要用wait()来实现计时逻辑,直接用time.sleep()即可,这也是最直观的方式。
可选优化:使用文本模式简化操作
如果觉得字节流操作麻烦,可以开启文本模式(Python 3.7+用text=True,旧版本用universal_newlines=True),这样可以直接写入字符串,不用转成字节:
import subprocess import time from subprocess import Popen, PIPE MCser = subprocess.Popen(["java.exe", "-Xms8024M", "-Xmx10096M", "-jar", "quilt-server-launch.jar"], stdout = PIPE, stdin = PIPE, stderr = PIPE, text=True) MCser.stdin.write('say test\n') MCser.stdin.flush() MCser.stdin.write('say Restart after 30s\n') MCser.stdin.flush() time.sleep(20) MCser.stdin.write('say Restart after 10s\n') MCser.stdin.flush() time.sleep(10) MCser.stdin.write('stop\n') MCser.stdin.flush()
内容的提问来源于stack exchange,提问作者Meowts
相关产品推荐
相关产品推荐

