我觉得这一定是某种范围问题,但经过大量研究后,我仍然感到难过。我正在构建一个小型的Minecraft服务器包装器,它目前正在使用以下代码(github上的完整源代码:Simple Minecraft Server Wrapper - app.py):
mc = subprocess.Popen(command, shell=True, stdin=subprocess.PIPE, cwd=results.path)
time.sleep(5)
while run == 1:
print '--- Checking for new versions in ' + str(check_for_new_versions_frequency) + ' seconds.'
time.sleep(check_for_new_versions_frequency)
print '--- Checking for a new version...'
mc.stdin.write('say SMSW - Checking for new version...\n')
mc.stdin.flush()
if up_to_date(current_ver) == False:
mc.stdin.write('say SMSW - New version detected, rebooting for update in 30 seconds...\n')
mc.stdin.flush()
这将启动服务器并以预定间隔检查新更新。这也将在游戏中发出消息,提醒连接的玩家它正在检查更新,并在需要更新时警告他们重新启动。这没有任何问题。
我想稍微清理代码并将消息传递,启动和关闭移动到一个名为ServerManager的单独类。该类可以启动服务器但消息传递不起作用。这是班级:
import time, subprocess
class ServerManager:
def __init__(self, path, server_file, xms=1, xmx=1, gui=False):
self.path = path
self.server_file = server_file
self.online = False
self.xms = xms
self.xmx = xmx
self.gui = gui
def start(self):
global process
command = 'java -jar -Xms' + str(self.xms) + 'G -Xmx' + str(self.xmx) + 'G ' + self.path + self.server_file
if self.gui == False: command += ' nogui'
print command
if self.path !='':self.process = subprocess.Popen(command, shell=True, stdin=subprocess.PIPE, cwd=self.path)
if self.path =='':self.process = subprocess.Popen(command, shell=True, stdin=subprocess.PIPE)
print self.server_process
self.online = True
def shutdown(self):
self.message('New version detected, server will be shutting down for maintenance in 1 minute.')
time.sleep(30)
self.message('Shutting down for maintenance in 30 seconds.')
time.sleep(20)
self.message('Shutting down for maintenance in 10 seconds.')
self.message('Have some diamonds for the trouble.')
self.message('give @a minecraft:diamond 5', true)
self.online = False
self.process.terminate()
del process
#Server chat can be passed as ServerManager.message('hello')
def message(self, message, command=False):
print self.server_process
if command == False:
self.process.stdin.write('### SMSW Message: ')
self.process.stdin.flush()
self.process.stdin.write(message)
self.process.stdin.flush()
else:
self.process.stdin.write(message)
self.process.stdin.flush()
最奇怪的部分是当我修改我的应用程序以利用这个类时,在应该发生服务器消息传递的点上我没有收到任何错误。它实际上并没有进行消息传递。我已经在启动和消息传递函数上完成了一个打印(进程)获取相同的对象引用,所以看起来它应该工作。服务器关闭也不起作用,我猜这是同样的问题,因为“服务器”对象似乎存在但由于某种原因无法访问。
以下是使用该类的修改后的主应用程序代码:
def main():
process_args()
server = ServerManager(results.path, mc_server, 1, 1)
global current_ver
global run
print '*' * 40
print '* Simple Minecraft Server Wrapper'
print '*' * 40
latest_ver = str(get_version())
if current_ver != latest_ver:
download_server(latest_ver)
current_ver = latest_ver
if not server.online:
server.start()
time.sleep(5)
while server.online:
print '--- Checking for new versions in ' + str(check_for_new_versions_frequency) + ' seconds.'
time.sleep(check_for_new_versions_frequency)
print '--- Checking for a new version...'
server.message('Checking for a new version...')
# Checking for new version
if not up_to_date(current_ver):
# new version detected
time.sleep(30)
server.online = False
time.sleep(5)
print '--- Server stopped'
main()
此处的输出是:
****************************************
* Simple Minecraft Server Wrapper
****************************************
--- The latest version of Minecraft is 1.8.8
--- Downloading 1.8.8
--- Download complete.
--- Started server with command: java -jar -Xms1G -Xmx1G minecraft_server.jar no
gui
<subprocess.Popen object at 0x029BBDB0>
[10:54:44] [Server thread/INFO]: Starting minecraft server version 1.8.8
[10:54:44] [Server thread/INFO]: Loading properties
[10:54:44] [Server thread/INFO]: Default game type: SURVIVAL
[10:54:44] [Server thread/INFO]: Generating keypair
[10:54:44] [Server thread/INFO]: Starting Minecraft server on *:25565
[10:54:44] [Server thread/INFO]: Using default channel type
[10:54:44] [Server thread/INFO]: Preparing level "world"
[10:54:44] [Server thread/INFO]: Preparing start region for level 0
[10:54:45] [Server thread/INFO]: Done (1.092s)! For help, type "help" or "?"
--- Checking for new versions in 20 seconds.
--- Checking for a new version...
<subprocess.Popen object at 0x029BBDB0>
--- The latest version of Minecraft is 1.8.8
--- Up to date.
--- Checking for new versions in 20 seconds.
--- Checking for a new version...
<subprocess.Popen object at 0x029BBDB0>
第一个子进程对象打印来自类中的start函数,第二个来自消息函数。引用符合您的预期,但stdout.write不起作用。
有什么想法吗?
答案 0 :(得分:1)
您正在向流程发送不同的命令。在第一个脚本中,您在第二个'say SMSW - Checking for new version...\n'
中发送'Checking for a new version...'
。
答案 1 :(得分:0)
这可能是您在重构代码中使用subprocess.Popen
的方式。具体来说,command
参数应该是列表,而不是字符串。
请参阅https://stackoverflow.com/a/12605520/2653356
PS。我个人放弃了subprocess
并且主要使用commands
模块。