如何使用cx_Freeze安装Python Windows服务?

6

我目前有一个Python文件,当使用python file_name.py运行时,会安装一个Windows服务,该服务可以在事件查看器中查看应用程序日志,并可使用sc stop service_name停止。然而,当使用cx_Freeze转换为可执行文件时,可执行文件运行时没有错误,但是该服务不再安装。这种情况发生在我仅运行可执行文件本身、运行service_name.exe --install service_name或运行sc create service_name binPath=service_path时。

我的setup.py文件大致如下:

from cx_Freeze import setup, Executable

options = {
'build_exe': {
    'packages': ['packagename'],
    'includes': ['ServiceHandler', 'cx_Logging']}
}

setup(name='cx_FreezeSampleService',
  version='0.1',
  description='Sample cx_Freeze Windows serice',
  executables=Executable('Config.py', base='Win32Service',
           targetName='cx_FreezeSampleService.exe'),
  options=options
  )

我的Config.py文件大致如下:

NAME = 'cx_FreezeSampleService%s'
DISPLAY_NAME = 'cx_Freeze Sample Service - %s'
MODULE_NAME = 'ServiceHandler'
CLASS_NAME = 'Handler'
DESCRIPTION = 'Sample service description'
AUTO_START = True
SESSION_CHANGES = False

最后,我的ServiceHandler.py文件看起来大致如下:
class Handler(object):
 def Initialize(self, Config):
    pass

 def Run(self):
    #code to run service

 def Stop(self):
    #code to stop service

这段代码参考了cx_Freeze官方源码中的示例(https://bitbucket.org/anthony_tuininga/cx_freeze/src/1282b6b6ee637738210113dd88c3c198d475340f/cx_Freeze/samples/service/?at=default),但是这段代码和示例看起来似乎都不能实际安装服务。感谢您的帮助!

我发现cx_Freeze示例中存在错误。函数initialize,run,stop必须用小写字母定义。例如,服务本身是通过cx_FreezeSampleService.exe --install test进行注册的。 - Martin Vyskočil
1个回答

2

这是一个老问题,但我通过开发人员的帮助成功将一个简单的Flask应用程序作为Windows服务运行。以下是相关链接: [https://github.com/marcelotduarte/cx_Freeze/tree/master/cx_Freeze/samples/service]

你需要设置所有想要执行的Windows服务操作。 下面是ServiceHandler.py文件的模板,你需要根据自己的应用程序进行适当地调整。

"""
Implements a simple service using cx_Freeze.
See below for more information on what methods must be implemented and how they
are called.
"""

import threading
import os
import sys
import cx_Logging




class Handler:

    # no parameters are permitted; all configuration should be placed in the
    # configuration file and handled in the Initialize() method
    def __init__(self):
        self.stopEvent = threading.Event()
        self.stopRequestedEvent = threading.Event()

    # called when the service is starting
    def initialize(self, configFileName):
        self.directory = os.path.dirname(sys.executable)
        cx_Logging.StartLogging(os.path.join(self.directory, "teste.log"), cx_Logging.DEBUG)
        #pass

    # called when the service is starting immediately after Initialize()
    # use this to perform the work of the service; don't forget to set or check
    # for the stop event or the service GUI will not respond to requests to
    # stop the service
    def run(self):
        cx_Logging.Debug("stdout=%r", sys.stdout)
        sys.stdout = open(os.path.join(self.directory, "stdout.log"), "a")
        sys.stderr = open(os.path.join(self.directory, "stderr.log"), "a")
        self.stopRequestedEvent.wait()
        self.stopEvent.set()

    # called when the service is being stopped by the service manager GUI
    def stop(self):
        self.stopRequestedEvent.set()
        self.stopEvent.wait()

只需要做出小的更正。executables 参数应该是一个 Executable 对象的列表。 除此之外,它就像魔术一样工作 :) 谢谢 - Omer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接