如何在Windows中将Python脚本作为服务运行?

python windows cross-platform

173114 观看

9回复

13298 作者的声誉

我正在描绘一组程序的架构,这些程序共享存储在数据库中的各种相互关联的对象。我希望其中一个程序充当服务,为这些对象的操作提供更高级别的接口,以及通过该服务访问对象的其他程序。

我目前的目标是将Python和Django框架作为实现该服务的技术。我很确定我想知道如何在Linux中守护Python程序。但是,它是系统应支持Windows的可选规范项。我对Windows编程没什么经验,也没有Windows服务的经验。

是否可以将Python程序作为Windows服务运行(即在没有用户登录的情况下自动运行)?我不一定要实现这一部分,但我需要大致了解如何做以决定是否按照这些方式进行设计。

编辑:感谢目前为止的所有答案,它们非常全面。我想知道一件事:Windows如何了解我的服务?我可以使用本机Windows实用程序进行管理吗? 在/etc/init.d中放置一个启动/停止脚本相当于什么?

作者: Hanno Fietz 的来源 发布者: 2008 年 8 月 28 日

回应 9


227

6392 作者的声誉

决定

是的你可以。我使用ActivePython附带的pythoncom库或者可以使用pywin32(Python for Windows扩展)安装。

这是简单服务的基本框架:

import win32serviceutil
import win32service
import win32event
import servicemanager
import socket


class AppServerSvc (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):
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_,''))
        self.main()

    def main(self):
        pass

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

您的代码将放在main()方法中 - 通常使用某种无限循环,可能会通过检查您在SvcStop方法中设置的标志来中断

作者: Ricardo Reyes 发布者: 2008 年 8 月 28 日

24

3263 作者的声誉

几乎任何Windows可执行文件都可以作为服务安装。

方法1:使用rktools.exe中的instsrv和srvany

对于Windows Home Server或Windows Server 2003(也适用于WinXP),Windows Server 2003资源工具包工具附带了可以串联使用的实用程序,称为instsrv.exesrvany.exe。有关如何使用这些工具的详细信息,请参阅此Microsoft知识库文章KB137890

对于Windows Home Server,这些实用程序有一个很好的用户友好包装,名为aptly“ Any Service Installer ”。

方法2:使用ServiceInstaller for Windows NT

还有另一个使用ServiceInstaller for Windows NT可在此下载)并使用python指令的替代方案。与名称相反,它也适用于Windows 2000和Windows XP。以下是有关如何将python脚本安装为服务的一些说明。

安装Python脚本

运行ServiceInstaller以创建新服务。(在这个例子中,假设python安装在c:\ python25)

Service Name  : PythonTest
Display Name : PythonTest 
Startup : Manual (or whatever you like)
Dependencies : (Leave blank or fill to fit your needs)
Executable : c:\python25\python.exe
Arguments : c:\path_to_your_python_script\test.py
Working Directory : c:\path_to_your_python_script

安装后,打开控制面板的服务小程序,选择并启动PythonTest服务。

在我最初的回答之后,我注意到已经在SO上发布了密切相关的问答。也可以看看:

我可以将Python脚本作为服务运行(在Windows中)吗?怎么样?

如何让Windows了解我用Python编写的服务?

作者: popcnt 发布者: 2009 年 2 月 28 日

31

582 作者的声誉

虽然几个星期前我对所选择的答案进行了投票,但与此同时我在这个主题上更加努力。感觉就像有一个特殊的Python安装和使用特殊模块来运行脚本作为服务是错误的方式。便携性等等呢?

我偶然发现了非常棒的非吸引服务管理器,这使得处理Windows服务非常简单明了。我想,既然我可以将选项传递给已安装的服务,我也可以选择我的Python可执行文件并将我的脚本作为选项传递。

我还没有尝试过这个解决方案,但我现在会这样做,并在整个过程中更新这篇文章。我也有兴趣在Windows上使用virtualenvs,所以我迟早会想出一个教程并在这里链接到它。

作者: mknaf 发布者: 2014 年 7 月 28 日

17

305 作者的声誉

实现此目的的最简单方法是使用本机命令sc.exe:

sc create PythonApp binPath= "C:\Python34\Python.exe --C:\tmp\pythonscript.py"
  1. https://technet.microsoft.com/en-us/library/cc990289(v=ws.11).aspx
  2. 使用sc.exe创建服务; 如何传入上下文参数
作者: pyOwner 发布者: 2016 年 12 月 7 日

-2

11 作者的声誉

pysc:Python上的服务控制管理器

作为从pythonhosted.org获取的服务运行的示例脚本:

from xmlrpc.server import SimpleXMLRPCServer

from pysc import event_stop


class TestServer:

    def echo(self, msg):
        return msg


if __name__ == '__main__':
    server = SimpleXMLRPCServer(('127.0.0.1', 9001))

    @event_stop
    def stop():
        server.server_close()

    server.register_instance(TestServer())
    server.serve_forever()

创建并启动服务

import os
import sys
from xmlrpc.client import ServerProxy

import pysc


if __name__ == '__main__':
    service_name = 'test_xmlrpc_server'
    script_path = os.path.join(
        os.path.dirname(__file__), 'xmlrpc_server.py'
    )
    pysc.create(
        service_name=service_name,
        cmd=[sys.executable, script_path]
    )
    pysc.start(service_name)

    client = ServerProxy('http://127.0.0.1:9001')
    print(client.echo('test scm'))

停止并删除服务

import pysc

service_name = 'test_xmlrpc_server'

pysc.stop(service_name)
pysc.delete(service_name)
pip install pysc
作者: Seliverstov Maksim 发布者: 2017 年 3 月 3 日

9

91 作者的声誉

逐步说明如何使其工作:

1-首先根据上面提到的基本骨架创建一个python文件。并将其保存到路径中,例如:“c:\ PythonFiles \ AppServerSvc.py”

import win32serviceutil
import win32service
import win32event
import servicemanager
import socket


class AppServerSvc (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):
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                          servicemanager.PYS_SERVICE_STARTED,
                          (self._svc_name_,''))
        self.main()

    def main(self):
        # Your business logic or call to any class should be here
        # this time it creates a text.txt and writes Test Service in a daily manner 
        f = open('C:\\test.txt', 'a')
        rc = None
        while rc != win32event.WAIT_OBJECT_0:
            f.write('Test Service  \n')
            f.flush()
            # block for 24*60*60 seconds and wait for a stop event
            # it is used for a one-day loop
            rc = win32event.WaitForSingleObject(self.hWaitStop, 24 * 60 * 60 * 1000)
        f.write('shut down \n')
        f.close()

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

2 - 在此步骤中,我们应该注册我们的服务。

管理员身份运行命令提示符,输入:

sc create TestService binpath =“C:\ Python36 \ Python.exe c:\ PythonFiles \ AppServerSvc.py”DisplayName =“TestService”start = auto

binpath的第一个参数是python.exe路径

binpath的第二个参数 是我们已经创建的python文件的路径

不要错过你应该在每个“ = ”符号后放一个空格。

如果一切正常,你应该看到

[SC] CreateService SUCCESS

现在你的python服务现在作为windows服务安装。您可以在Service Manager和注册表中看到它:

HKEY_LOCAL_MACHINE \系统\ CurrentControlSet \服务\ TestService的

3-现在好。您可以在服务管理器上启动服务。

您可以执行提供此服务框架的每个python文件。

作者: Seckin Sanli 发布者: 2017 年 6 月 29 日

11

111 作者的声誉

最简单的方法是使用:NSSM - 非吸吮服务管理器:

1 - 在https://nssm.cc/download上下载

2 - 将python程序安装为服务:以管理员身份运行Win提示符

c:> nssm.exe安装WinService

3 - 在NSSM的控制台上:

路径:C:\ Python27 \ Python27.exe

启动目录:C:\ Python27

参数:c:\ WinService.py

4 - 检查services.msc上创建的服务

作者: Adriano R P L 发布者: 2017 年 9 月 27 日

0

302 作者的声誉

我开始使用pywin32作为服务托管。

一切都很顺利,但我遇到了服务无法在30秒内启动的问题(Windows的默认超时)。这对我来说至关重要,因为Windows启动是在一台物理机器上托管的多个虚拟机上同时发生的,并且IO负载非常大。错误消息是:

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

Error 7009: Timeout (30000 milliseconds) waiting for the <ServiceName> service to connect.

我与pywin进行了很多战斗,但最终使用了NSSM,正如在这个答案中提出的那样。迁移到它很容易。

作者: flam3 发布者: 2018 年 10 月 12 日

0

1601 作者的声誉

接受的答案使用win32serviceutil有效,但很复杂,使调试更难。使用NSSM非吸吮服务管理器)更容易。你只需要一个普通的python程序,然后使用NSSM在不到一分钟的时间内将其安装为服务:

从提升(管理员)命令提示符运行nssm.exe install NameOfYourService并填写以下选项:

  • 路径 :( python.exe的路径例如C:\Python27\Python.exe
  • 参数 :(你的python脚本的路径,例如c:\path\to\program.py

顺便说一句,如果你的程序打印出你想要保存在日志文件中的有用消息,NSSM也可以为你处理这个问题。

作者: ndemou 发布者: 2018 年 11 月 10 日
32x32