CherryPy作为Windows服务的例子



我看到很多人都在为此苦苦挣扎 - 我也遇到了问题。如果有人可以帮助使 CherryPy 服务示例正常工作,那将是一个很大的帮助。解释这些问题将不胜感激。

有一个

CherryPy作为Windows服务的例子,可以在:CherryPyWiki。我正在努力让它工作。这是我的代码:

"""
The most basic (working) CherryPy 3.0 Windows service possible.
Requires Mark Hammond's pywin32 package.
"""
import cherrypy
import win32serviceutil
import win32service
import win32event
import servicemanager
class HelloWorld:
    """ Sample request handler class. """
    def index(self):
        return "Hello world!"
    index.exposed = True

class MyService(win32serviceutil.ServiceFramework):
    """NT Service."""
    _svc_name_ = "CherryPyService"
    _svc_display_name_ = "CherryPy Service"
    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        # create an event that SvcDoRun can wait on and SvcStop
        # can set.
        self.stop_event = win32event.CreateEvent(None, 0, 0, None)
    def SvcDoRun(self):
        self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_,''))
        cherrypy.tree.mount(HelloWorld(), '/')
        # in practice, you will want to specify a value for
        # log.error_file below or in your config file.  If you
        # use a config file, be sure to use an absolute path to
        # it, as you can't be assured what path your service
        # will run in.
        cherrypy.config.update({
            'global':{
                'engine.autoreload.on': False,
                'log.screen': False,
                'log.error_file': 'c:\MG\temp\CherryPy_Sample_Service.log',
                'engine.SIGHUP': None,
                'engine.SIGTERM': None
                }
            })
        # set blocking=False so that start() does not block
        cherrypy.server.quickstart()
        cherrypy.engine.start(blocking=False)
        # now, block until our event is set...
        win32event.WaitForSingleObject(self.stop_event, win32event.INFINITE)
        self.ReportServiceStatus(win32service.SERVICE_RUNNING)
    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        cherrypy.server.stop()
        win32event.SetEvent(self.stop_event)
if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(MyService)

以上与链接的示例不同。我已添加

  • self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
  • self.ReportServiceStatus(win32service.SERVICE_RUNNING)作为SvcDoRun的第一个和最后一个陈述
  • 'log.error_file': 'c:\MG\temp\CherryPy_Sample_Service.log',按照维基的指示

重要说明:虽然可以使用控制台python cherrypy_sample_service.py install安装服务,但无法使用python cherrypy_sample_service.py start命令启动它。这样做的原因是,以这种方式创建的服务将引用python可执行文件,它不是设计为服务。

因此,为了进一步测试,我使用以下方法编译了代码:

from cx_Freeze import setup, Executable
exe = Executable(
    script='cherrypy_sample_service.py'
)

build_options = {'includes': ['cherrypy', 'win32serviceutil', 'win32service', 'win32event', 'servicemanager']}
setup(
        name = "CherryPy Sample Service",
        version = "0.1",
        service = ["cherrypy_sample_service.py"],
        options = {"build_exe" : build_options},
        executables = [exe])

在构建过程中,我收到以下警告:

Python27Applibdistutilsdist.py:267: UserWarning: Unknown distribution option: 'service'
warnings.warn(msg)

我已根据以下堆栈问题答案添加了此选项。

现在我可以打电话给cherrypy_sample_service installcherrypy_sample_service removecherrypy_sample_service update。但是,尝试运行服务(从服务或通过cherrypy_sample_service start(会导致以下错误:

Error starting service: The service did not respond to the start or control request in a timely fashion.

我被困住了。日志文件甚至不会被创建。你能帮我运行这个例子吗?我想如果我们能解释并运行一个示例,这对其他在相关问题上苦苦挣扎的人也很有用。谢谢!

我刚刚从您提到的 wiki 页面中获取了 3.1 的版本,它可以立即工作。 即它从命令行安装、启动和停止,因为它从服务管理 GUI 启动和停止。

"""
The most basic (working) CherryPy 3.1 Windows service possible.
Requires Mark Hammond's pywin32 package.
"""
import cherrypy
import win32serviceutil
import win32service
class HelloWorld:
    """ Sample request handler class. """
    @cherrypy.expose
    def index(self):
        return "Hello world!"

class MyService(win32serviceutil.ServiceFramework):
    """NT Service."""
    _svc_name_ = "CherryPyService"
    _svc_display_name_ = "CherryPy Service"
    def SvcDoRun(self):
        cherrypy.tree.mount(HelloWorld(), '/')
        # in practice, you will want to specify a value for
        # log.error_file below or in your config file.  If you
        # use a config file, be sure to use an absolute path to
        # it, as you can't be assured what path your service
        # will run in.
        cherrypy.config.update({
            'global':{
                'log.screen': False,
                'engine.autoreload.on': False,
                'engine.SIGHUP': None,
                'engine.SIGTERM': None
                }
            })
        cherrypy.engine.start()
        cherrypy.engine.block()
    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        cherrypy.engine.exit()
        self.ReportServiceStatus(win32service.SERVICE_STOPPED) 
        # very important for use with py2exe
        # otherwise the Service Controller never knows that it is stopped !
if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(MyService)

测试环境是:XP SP3,Python 2.7.5,CherryPy 3.3,0,pywin32 218.4。

调试提示

无需生成二进制文件即可运行服务。当您从源代码安装 pywin32 服务时,它会使用 %PYDIR%Libsite-packageswin32pythonservice.exe 作为服务代理。即所有服务都将其作为运行命令行,REG:HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesCherryPyServicePythonClass定义服务的实际 Python 类。

从命令行运行pythonservice.exe并确保它运行没有错误 (1(。您可能还会注意到,有一个调试选项允许您将服务的 stdout 和 stderr 附加到终端 (2(。

确保没有防火墙软件阻止pythonservice.exe进行网络活动。

最后我

找到了解决方案 - 我已经下载并重新安装了 pywin32...一切正常!:)

最后要说几点:

  • 服务从编辑器开始正常 - 不需要编译。
  • 'log.error_file': 'c:\somedircherypy_sample_service.log' 添加到cherrypy.config.update有助于验证服务是否已启动并运行

在尝试调试问题时,我发现一旦win32serviceutil.HandleCommandLine调用StartService并进入代码的这一部分:

    try:
        win32service.StartService(hs, args)
    finally:
        win32service.CloseServiceHandle(hs)

我无法踏入win32service.StartService.我无法找到该文件,这就是我重新安装 pywin32 的原因。

我只能有一些错误消息 - 希望这对其他人有帮助。

最新更新