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

Resuelto Hanno Fietz asked hace 16 años • 14 respuestas

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

Actualmente estoy apuntando a Python y el marco Django como tecnologías para implementar ese servicio. Estoy bastante seguro de que descubrí cómo demonizar el programa Python en Linux. Sin embargo, es un elemento de especificación opcional que el sistema debería ser compatible con Windows. Tengo poca experiencia con la programación de Windows y ninguna experiencia con los servicios de Windows.

¿Es posible ejecutar programas 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 poder decidir si diseñar según estas líneas.

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

Hanno Fietz avatar Aug 28 '08 21:08 Hanno Fietz
Aceptado

Sí tu puedes. Lo hago usando las bibliotecas de pythoncom que vienen incluidas con ActivePython o que 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 main()método, generalmente con algún tipo de bucle infinito que podría interrumpirse al marcar una bandera, que usted establece en el SvcStopmétodo.

Ricardo Reyes avatar Aug 28 '2008 14:08 Ricardo Reyes

La forma más sencilla es utilizar: NSSM, el administrador de servicios sin succión. Simplemente descárguelo y descomprímalo en la ubicación que elija. Es una utilidad autónoma, de alrededor de 300 KB (mucho menos que instalar todo el paquete pywin32 solo para este propósito) y no necesita "instalación". El zip contiene una versión de 64 bits y una de 32 bits de la utilidad. Cualquiera de los dos debería funcionar bien en los sistemas actuales (puede usar la versión de 32 bits para administrar servicios en sistemas de 64 bits).

Enfoque GUI

1 - instale el programa Python como servicio. Abra un mensaje de Win como administrador

c:\>nssm.exe install WinService

2 - En la consola GUI de NSSM:

ruta: C:\Python27\Python27.exe

Directorio de inicio: C:\Python27

Argumentos: c:\WinService.py

3 - verifique los servicios creados en services.msc

Enfoque de secuencias de comandos (sin GUI)

Esto es útil si su servicio debe ser parte de un procedimiento automatizado y no interactivo que puede estar fuera de su control, como un script de instalación o por lotes. Se supone que los comandos se ejecutan con privilegios administrativos.

Para mayor comodidad, los comandos se describen aquí simplemente haciendo referencia a la utilidad como nssm.exe. Sin embargo, es aconsejable hacer referencia a él de manera más explícita en las secuencias de comandos con su ruta completa c:\path\to\nssm.exe, ya que es un ejecutable autónomo que puede estar ubicado en una ruta privada que el sistema no conoce.

1. Instalar el servicio

Debe especificar un nombre para el servicio, la ruta al ejecutable de Python adecuado y la ruta al script:

nssm.exe install ProjectService "c:\path\to\python.exe" "c:\path\to\project\app\main.py"

Más explícitamente:

nssm.exe install ProjectService 
nssm.exe set ProjectService Application "c:\path\to\python.exe"
nssm.exe set ProjectService AppParameters "c:\path\to\project\app\main.py"

Alternativamente, es posible que desee que su aplicación Python se inicie como un módulo de Python. Un enfoque sencillo es decirle a nssm que necesita cambiar al directorio de inicio adecuado, como lo haría usted mismo al iniciar desde un shell de comandos:

nssm.exe install ProjectService "c:\path\to\python.exe" "-m app.main"
nssm.exe set ProjectService AppDirectory "c:\path\to\project"

Este enfoque funciona bien con entornos virtuales e instalaciones de Python autónomas (integradas). Sólo asegúrese de haber resuelto adecuadamente cualquier problema de ruta en esos entornos con los métodos habituales. nssm tiene una forma de configurar variables de entorno (por ejemplo, PYTHONPATH) si es necesario y también puede iniciar scripts por lotes.

2. Para iniciar el servicio

nssm.exe start ProjectService 

3. Para detener el servicio

nssm.exe stop ProjectService

4. Para eliminar el servicio , especifique el confirmparámetro para omitir la confirmación interactiva.

nssm.exe remove ProjectService confirm
Adriano P avatar Sep 27 '2017 14:09 Adriano P

Aunque voté a favor de 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 servicio es simplemente la forma incorrecta. ¿Qué pasa con la portabilidad y demás?

Me topé con el maravilloso Non-sucking Service Manager , que hizo que manejar los servicios de Windows fuera realmente sencillo y sensato. Pensé que como podía pasar opciones a un servicio instalado, también podía seleccionar mi ejecutable de Python y pasar mi script como una 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 tarde o temprano podría crear un tutorial y vincularlo aquí.

mknaf avatar Jul 28 '2014 13:07 mknaf

La forma más sencilla de lograr esto es utilizar 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?
pyOwner avatar Dec 07 '2016 12:12 pyOwner