Python 3可执行作为Windows服务

时间:2014-02-23 08:51:33

标签: python windows service cx-freeze

我正在尝试在python中编写一个Windows服务,但棘手的部分是我想将它部署在没有python的机器上。 我已经成功创建了一个像this这样的服务,如果我从我的机器上运行它就可以了。当我尝试将其转换为exe然后尝试安装它时,问题就开始了。 首先我尝试使用cx_freeze服务示例(见here),setup.py如下所示:

from cx_Freeze import setup, Executable

options = {'build_exe': {'includes': ['ServiceHandler']}}

executables = [Executable('Config.py', base='Win32Service', targetName='gsr.exe')]

setup(name='GSR',
    version='0.1',
    description='GSR SERVICE',
    executables=executables,
    options=options
    )

和config.py是:

NAME = 'GSR_%s'
DISPLAY_NAME = 'GSR TEST - %s'
MODULE_NAME = 'ServiceHandler'
CLASS_NAME = 'Handler'
DESCRIPTION = 'Sample service description'
AUTO_START = True
SESSION_CHANGES = False

但是当我尝试构建它(python setup.py build)时,我收到一个错误: “cx_Freeze.freezer.ConfigError:没有名为Win32Service的基地”

其次,我尝试使用常规cx_freeze设置,exe我得到安装服务正常但一旦我尝试启动它我得到一个错误: “错误1053:服务没有及时响应启动或控制请求”

setup.py - python 3.3 regualr exe,安装服务,但在尝试启动时发送错误:

from cx_Freeze import setup, Executable

packages = ['win32serviceutil','win32service','win32event','servicemanager','socket','win32timezone','cx_Logging','ServiceHandler']
build_exe_options = {"packages": packages}
executable = [Executable("ServiceHandler.py")]


setup(  name = "GSR_test",
        version = "1.0",
        description = "GSR test service",
        options = {"build_exe": build_exe_options},
        executables = executable)

最后,我设法使用py2exe在python 2.7中使用它,但是python 3.3不能使用py2exe而我的代码是3.3​​

我猜问题是在使用cx_freeze的setup.py im的配置中。 任何想法??

我的ServiceHandler:

import pythoncom
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
from test import test
import threading

class AppServerSvc (win32serviceutil.ServiceFramework):
    _svc_name_ = "GSR_test"
    _svc_display_name_ = "GSR test Service"

    def __init__(self,args):
        win32serviceutil.ServiceFramework.__init__(self,args)
        self.hWaitStop = win32event.CreateEvent(None,0,0,None)
        socket.setdefaulttimeout(60)
        self.app = test()
        self.flag = threading.Event()

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        self.flag.set()

    def SvcDoRun(self):
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_,''))
        self.main()

    def main(self):
        t = threading.Thread(target=self.app.run)
        t.start()
        self.flag.wait()
        raise SystemExit

if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(AppServerSvc)

Setup.py,python 2.7使用py2exe工作:(取自here

from distutils.core import setup
import py2exe

setup(  service = ["ServiceHandler"],
        description = "SERVICE TEST",
        modules = ["GSR_test"],
        cmdline_style='pywin32', ) 

谢谢, 阿米特

3 个答案:

答案 0 :(得分:8)

tldr 使用pyinstaller进行Python 3.5 Windows Service构建:gist

这是一个简单的Windows服务,使用python:

WindowsService.py

import servicemanager
import socket
import sys
import win32event
import win32service
import win32serviceutil


class TestService(win32serviceutil.ServiceFramework):
    _svc_name_ = "TestService"
    _svc_display_name_ = "Test Service"

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        socket.setdefaulttimeout(60)

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)

    def SvcDoRun(self):
        rc = None
        while rc != win32event.WAIT_OBJECT_0:
            with open('C:\\TestService.log', 'a') as f:
                f.write('test service running...\n')
            rc = win32event.WaitForSingleObject(self.hWaitStop, 5000)


if __name__ == '__main__':
    if len(sys.argv) == 1:
        servicemanager.Initialize()
        servicemanager.PrepareToHostSingle(TestService)
        servicemanager.StartServiceCtrlDispatcher()
    else:
        win32serviceutil.HandleCommandLine(TestService)

使用pyinstaller(pip install pyinstaller)和python 3.5:

创建一个exe
(env)$ python -V
Python 3.5.2

(env)$ pip freeze
PyInstaller==3.2

(env)$ pyinstaller -F --hidden-import=win32timezone WindowsService.py

安装并运行服务

(env) dist\WindowsService.exe install
Installing service TestService
Service installed

(env) dist\WindowsService.exe start
Starting service TestService

检查C:\\TestService.log文件。

停止并清理

(env) dist\WindowsService.exe stop
(env) dist\WindowsService.exe remove

答案 1 :(得分:1)

由于was updated with Python 3.x support,cx_Freeze项目中出现了Win32Service this thread。该用户最初遇到了您报告的相同问题,因此我假设这也将解决您的问题。

根据报告的错误,当Freezer.py中的_GetBaseFileName()无法找到已编译的Win32Service.exe时,会导致该错误。当cx_Freeze获取built/installed时,应该构建此可执行文件。

如果问的不是太多,可以在已安装的cx_Freeze安装目录中搜索“Win32Service.exe”并确认它是否存在。希望这能让你更近一步。

答案 2 :(得分:1)

我已编辑Win32Service.c src中的cx_freeze python3支持

使用一些预处理器命令编辑它,也支持python2(但尚未测试python2)

  1. pypi下载cx_freeze的来源并将其解压缩
  2. 下载cx_logging并将其解压缩到cx_freeze-4.3.4目录
  3. 使用my edited version
  4. 替换Win32Service.c中的cx_Freeze-4.3.4\source\bases文件
  5. setup.pyif moduleInfo is not None and sys.version_info[:2] < (3, 0):
  6. if moduleInfo is not None:中修改第170行
  7. python setup.py build目录中运行cx_freeze-4.3.4(您必须安装MSC才能编译C源文件)
  8. cx_Freeze-4.3.4\build\lib.win32-3.4\cx_Freeze\bases\Win32Service.exe复制到C:\Python34\Lib\site-packages\cx_Freeze\bases(或安装python3的路径)
  9. 现在您可以使用Win32Service基础创建冻结的exe(不再是cx_Freeze.freezer.ConfigError: no base named Win32Service错误)
相关问题