移入函数

时间:2015-08-29 14:53:23

标签: python python-2.7

我觉得这一定是某种范围问题,但经过大量研究后,我仍然感到难过。我正在构建一个小型的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不起作用。

有什么想法吗?

2 个答案:

答案 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模块。