Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

windows下实现python后台进程 #20

Open
coneo opened this issue Jul 1, 2015 · 7 comments
Open

windows下实现python后台进程 #20

coneo opened this issue Jul 1, 2015 · 7 comments
Labels

Comments

@coneo
Copy link
Owner

coneo commented Jul 1, 2015

qq20150701074358

python作为一门脚本语言,其丰富的库使其能够干的事情尤其多。我们或许会有这样的需求,把python程序作为后台进程启动。也就是说,没有界面,没有终端。相当于linux下的一个概念:守护进程(daemon)。

如果你的程序是跑在linux上,那么只要你理解了python os.fork的使用,就可以自己构建出一个daemon的实现。windows下不支持fork,但是有另外一个概念:服务(service)。通常我们在windows下安装一个软件的时候,如果它有后台服务的功能,那么它都会注册一个服务,比如:google更新服务、QQ音乐服务、VMWare等。通过路径:计算机 -> 管理 -> 服务和应用程序 -> 服务 可以查看服务列表。我们可以对服务进行控制:启动、停止、重启动。

如此看来,windows下服务的概念就相当于后台进程了,它不必有界面和终端,我们可以在服务列表对其进行控制(启动、停止、重启动)。接下来,我们就来看看如何利用python实现一个服务。

软件安装准备

除了需要python包之外,还需要一个windows下的python库:pywin32。具体安装过程就不重述了,测试pywin32是否安装好的方法是:

     python >> import win32service

如果无报错,则表示pywin32安装成功。

服务类

其核心类为win32serviceutil.ServiceFramework,代表服务的基类,实现我们自己的服务需要继承该类。

成员变量:

     _svc_name_ = "your service name"
     _svc_display_name_ = "your service display name"
     _svc_description_ = "your service description"

接口:

     SvcDoRun 启动该服务的回调
     SvcStop 结束该服务的回调

一般来说,我们把程序的主逻辑放到SvcDoRun 里,程序结束的清理工作放到SvcStop 里。ServiceFramework 自己有一套对服务的控制机制,大概是如下的样子:

    install     ->      调用windows服务API来安装一个服务
    remove     ->     调用windows服务API来卸载一个服务
    start     ->     SvcDoRun 
    stop     ->     SvcStop 
    restart     ->     SvcStop  -> SvcDoRun 

另外,在python程序的main下, 要使用pywin32的接口来指定需要通过命令行执行的类:

     win32serviceutil.HandleCommandLine(YourClass)

实现一个服务类

import win32service
import win32serviceutil
import win32event

class PySvc(win32serviceutil.ServiceFramework):
    # you can NET START/STOP the service by the following name
    _svc_name_ = "ServicePython"
    # this text shows up as the service name in the Service
    # Control Manager (SCM)
    _svc_display_name_ = "ServicePython Service"
    # this text shows up as the description in the SCM
    _svc_description_ = "This service writes stuff to a file"

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self,args)
        # create an event to listen for stop requests on
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)

    # core logic of the service   
    def SvcDoRun(self):
        import servicemanager

        self.start()
        win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)

    # called when we're being shut down    
    def SvcStop(self):
        # tell the SCM we're shutting down
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        # fire the stop event
        win32event.SetEvent(self.hWaitStop)
        self.stop()

    def start(self):
        pass

    def stop(self):
        pass

这里我们定义一个类PySvc,并提供了两个接口 start和stop。使用的时候,我们只需继承该类,并重写start和stop接口即可。如下的一个实例:

class MyS(PySvc):
    def start(self):
        logger.debug('my starting ..... ')

    def stop(self):
        logger.debug('my stopping ....')

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

这样以来,我们可以进行以下操作了:

安装服务: python svc.py install
启动服务: python svc.py start
关闭服务: python svc.py stop
重启服务: python svc.py restart
卸载服务: python svc.py remove

@coneo coneo added the python label Jul 1, 2015
@hepingtao
Copy link

按以上的例子重写start接口,安装服务成功后,启动服务报错:

Error starting service: 服务没有及时响应启动或控制请求。

是否start方法还需包含其他处理逻辑?

@restran
Copy link

restran commented Aug 17, 2017

@hx78
Copy link

hx78 commented Nov 17, 2017

我遇到同样的问题,服务注册成功后,执行文件是"C:\Python33\lib\site-packages\win32\PythonService.exe",启动时提示
Error starting service: 服务没有及时响应启动或控制请求。

pywin32版本为219 @hepingtao @restran

@PumayHui
Copy link

@hx78 我也遇到同样的问题了,请问您是怎么解决的呢?非常感谢~

@JesseZhang
Copy link

同问

@WillZt
Copy link

WillZt commented Mar 21, 2018

把你的python的路径添加到系统变量的Path中,而不仅仅在用户的系统变量中添加~

@AngelLiang
Copy link

问题:服务没有及时响应启动或控制请求

资源管理器进入Lib\site-packages\win32目录,双击pythonservice.exe看看能不能运行,如果是提示少了pywintypes36.dll,可以到Lib\site-packages\pywin32_system32目录下拷贝过去,放到与pythonservice.exe同一目录下。

我在Win10+Py3.6环境下已经测试成功。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants