¿Cómo se ejecuta un script de Python como un servicio en Windows?

Estoy dibujando la architecture para un conjunto de progtwigs que comparten varios objetos interrelacionados almacenados en una base de datos. Quiero que uno de los progtwigs actúe como un servicio que proporcione una interfaz de nivel superior para las operaciones en estos objetos, y que los otros progtwigs accedan a los objetos a través de ese servicio.

Actualmente estoy apuntando a Python y al framework Django como las tecnologías para implementar ese servicio con. Estoy bastante seguro de que me doy cuenta de cómo demonizar el progtwig Python en Linux. Sin embargo, es un elemento de especificación opcional que el sistema debe admitir Windows. Tengo poca experiencia con la progtwigción de Windows y ninguna experiencia con los servicios de Windows.

¿Es posible ejecutar progtwigs de Python como un servicio de Windows (es decir, ejecutarlo automáticamente sin que el usuario inicie sesión)? No necesariamente tendré que implementar esta parte, pero necesito una idea aproximada de cómo se haría para decidir si se debe diseñar en esta línea.

Edit: Gracias por todas las respuestas hasta ahora, son bastante completas. Me gustaría saber una cosa más: ¿Cómo reconoce Windows mi servicio? ¿Puedo administrarlo con las utilidades nativas de Windows? ¿Cuál es el equivalente a poner un script de inicio / parada en /etc/init.d?

Sí tu puedes. Lo hago utilizando las bibliotecas de pythoncom que vienen incluidas con ActivePython o se pueden instalar con pywin32 ( extensiones de Python para Windows).

Este es un esqueleto básico para un servicio simple:

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) 

Su código iría en el método main() , generalmente con algún tipo de bucle infinito que podría interrumpirse marcando una bandera, que estableció en el método SvcStop

A pesar de que aumenté la respuesta elegida hace un par de semanas, mientras tanto luché mucho más con este tema. Parece que tener una instalación especial de Python y usar módulos especiales para ejecutar un script como un servicio es simplemente una manera incorrecta. ¿Qué pasa con la portabilidad y tal?

Me encontré con el maravilloso administrador de servicios que no chupaba , lo que lo hacía realmente simple y sensato para lidiar con los servicios de Windows. Pensé que, dado que podía pasar opciones a un servicio instalado, podría seleccionar mi ejecutable Python y pasar mi script como opción.

Todavía no he probado esta solución, pero lo haré ahora mismo y actualizaré esta publicación a lo largo del proceso. También estoy interesado en usar virtualenvs en Windows, por lo que podría encontrar un tutorial tarde o temprano y vincularlo aquí.

Hay un par de alternativas para instalar como servicio prácticamente cualquier ejecutable de Windows.

Método 1: use instsrv y srvany desde rktools.exe

Para Windows Home Server o Windows Server 2003 (también funciona con WinXP), las herramientas del Kit de recursos de Windows Server 2003 vienen con utilidades que se pueden usar en conjunto para esto, llamadas instsrv.exe y srvany.exe . Consulte este artículo KB137890 de Microsoft KB para obtener detalles sobre cómo usar estos utils.

Para Windows Home Server, hay un excelente contenedor fácil de usar para estas utilidades llamado apropiadamente ” Cualquier instalador de servicios “.

Método 2: usar ServiceInstaller para Windows NT

Hay otra alternativa que usa ServiceInstaller para Windows NT (se puede descargar aquí ) con instrucciones de Python disponibles . Contrariamente al nombre, también funciona con Windows 2000 y Windows XP. Aquí hay algunas instrucciones sobre cómo instalar un script de Python como un servicio.

Instalando un script de Python

Ejecute ServiceInstaller para crear un nuevo servicio. (En este ejemplo, se supone que python está instalado en 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 

Después de la instalación, abra el applet de Servicios del Panel de Control, seleccione e inicie el servicio PythonTest.

Después de mi respuesta inicial, noté que había preguntas y respuestas relacionadas estrechamente relacionadas con SO. Ver también:

¿Puedo ejecutar un script de Python como un servicio (en Windows)? ¿Cómo?

¿Cómo hago para que Windows conozca un servicio que he escrito en Python?

La forma más sencilla de lograr esto es usar el comando nativo sc.exe:

 sc create PythonApp binPath= "C:\Python34\Python.exe --C:\tmp\pythonscript.py" 

Referencias:

  1. https://technet.microsoft.com/en-us/library/cc990289(v=ws.11).aspx
  2. Al crear un servicio con sc.exe, ¿cómo pasar parámetros de contexto?

La forma más sencilla es usar: NSSM – el administrador de servicios de no succión:

1 – hacer descarga en https://nssm.cc/download

2: instale el progtwig python como servicio: pregunte Win como administrador

c:> nssm.exe instala WinService

3 – En la consola de NSSM:

ruta: C: \ Python27 \ Python27.exe

Directorio de inicio: C: \ Python27

Argumentos: c: \ WinService.py

4 – verifique los servicios creados en services.msc

Explicación paso a paso de cómo hacer que funcione:

1- Primero crea un archivo python de acuerdo con el esqueleto básico mencionado anteriormente. Y guárdelo en una ruta, por ejemplo: “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 – En este paso debemos registrar nuestro servicio.

Ejecute el símbolo del sistema como administrador y escriba como:

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

el primer argumento de binpath es la ruta de python.exe

El segundo argumento de binpath es la ruta de su archivo python que ya creamos.

No se pierda que debe poner un espacio después de cada signo ” = “.

Entonces si todo está bien, deberías ver

[SC] CreateService SUCCESS

Ahora su servicio de Python está instalado como servicio de Windows ahora. Puedes verlo en Service Manager y registro en:

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ TestService

3- ok ahora. Puede iniciar su servicio en el administrador de servicios.

Puede ejecutar todos los archivos de python que proporcionan este esqueleto de servicio.

Comencé a alojar como un servicio con pywin32 .

Todo estaba bien, pero me encontré con el problema de que el servicio no pudo iniciarse dentro de los 30 segundos (tiempo de espera predeterminado para Windows) en el inicio del sistema. Fue fundamental para mí porque el inicio de Windows se llevó a cabo simultáneamente en varias máquinas virtuales alojadas en una máquina física, y la carga de IO fue enorme. Los mensajes de error fueron:

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 service to connect.

Peleé mucho con pywin, pero terminé usando NSSM como se propuso en esta respuesta . Era muy fácil migrar a él.

La respuesta aceptada con win32serviceutil funciona, pero es complicada y hace que la depuración y los cambios sean más difíciles. Es mucho más fácil usar NSSM ( el administrador de servicios para no chupar) . Usted escribe y depura cómodamente un progtwig normal de Python y cuando finalmente funciona, utiliza NSSM para instalarlo como un servicio en menos de un minuto:

Desde un indicador de comando elevado (admin), ejecuta nssm.exe install NameOfYourService y completa estas opciones:

  • ruta : (la ruta a python.exe, por ejemplo, C:\Python27\Python.exe )
  • Argumentos : (la ruta a su script de python, por ejemplo, c:\path\to\program.py )

Por cierto, si su progtwig imprime mensajes útiles que desea mantener en un archivo de registro, NSSM también puede manejar esto y mucho más para usted.

pysc: Service Control Manager en Python

Ejemplo de secuencia de comandos para ejecutar como un servicio tomado de 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() 

Crear e iniciar servicio

 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')) 

Detener y eliminar servicio

 import pysc service_name = 'test_xmlrpc_server' pysc.stop(service_name) pysc.delete(service_name) 
 pip install pysc