como - ejecutar un script desde python
¿Cómo se ejecuta un script de Python como un servicio en Windows? (9)
Estoy dibujando la arquitectura para 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 las 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 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 programa Python en Linux. Sin embargo, es un elemento de especificación opcional que el sistema debe admitir Windows. Tengo poca experiencia con la programación de Windows y ninguna experiencia con los servicios de Windows.
¿Es posible ejecutar programas 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?
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 utilizar 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 chupa , lo que hace que sea realmente simple y sensato tratar 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í.
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 crítico para mí porque el inicio de Windows se realizó 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 <ServiceName> service to connect.
Peleé mucho con pywin, pero terminé usando NSSM como se propuso en esta respuesta . Era muy fácil migrar a él.
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 cada archivo de python que proporciona este esqueleto de servicio.
Hay un par de alternativas para instalar como un 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 Microsoft KB para obtener detalles sobre cómo usar estos utils.
Para Windows Home Server, hay un gran contenedor fácil de usar para estas utilidades llamado aptly " Any Service Installer ".
Método 2: Use 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 ya 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"
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 programa python como un 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 - comprobar los servicios creados en services.msc
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) . Escribes y depuras cómodamente un programa de Python normal y cuando finalmente funciona, usas 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 programa imprime mensajes útiles que desea mantener en un archivo de registro, NSSM también puede manejar esto y mucho más para usted.
Sí tu puedes. Lo hago utilizando las bibliotecas de pythoncom que vienen incluidas con ActivePython o se pueden instalar con pywin32 ( pywin32 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
pysc: Service Control Manager en Python
Ejemplo de script 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