Comment exécuter un script Python en tant que service dans Windows?
je dessine l'architecture d'un ensemble de programmes qui partagent divers objets interdépendants stockés dans une base de données. Je veux que l'un des programmes agisse comme un service qui fournit une interface de niveau supérieur pour les opérations sur ces objets, et les autres programmes pour accéder aux objets par ce service.
je vise actuellement Python et le cadre Django comme les technologies pour mettre en œuvre ce service. Je suis presque sûr que j'ai trouvé comment démoniser le programme Python sous Linux. Cependant, il s'agit d'un élément optionnel spec que le système devrait prendre en charge Windows. J'ai peu d'expérience avec la programmation sous Windows et pas d'expérience avec tous les services de Windows.
est-il possible d'exécuter des programmes Python comme un service Windows (I. E. l'exécuter automatiquement sans connexion utilisateur)? Je n'aurai pas nécessairement à mettre en œuvre cette partie, mais j'ai besoin d'une idée approximative de la façon dont il serait fait afin de décider s'il faut concevoir le long de ces lignes.
Edit: Merci pour toutes les réponses jusqu'à présent, ils sont assez complètes. Je voudrais savoir encore une chose: comment Windows est-il au courant de mon service? Puis-je le gérer avec les utilitaires Windows natifs? qu'est-ce qui équivaut à mettre un script start/stop dans /etc/init.d?
8 réponses
Oui, vous pouvez. Je le fais en utilisant les bibliothèques pythoncom qui sont incluses avec ActivePython ou peuvent être installées avec pywin32 (Python pour extensions Windows).
c'est un squelette de base pour un service 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)
votre code irait dans la méthode main()
- généralement avec une sorte de boucle infinie qui pourrait être interrompue par la vérification d'un drapeau, que vous mettez dans le SvcStop
méthode
bien que j'ai mis en doute la réponse choisie il y a quelques semaines, entre-temps j'ai eu beaucoup plus de mal avec ce sujet. C'est comme avoir une installation Python spéciale et utiliser des modules spéciaux pour exécuter un script comme un service est tout simplement la mauvaise façon. Quid de la portabilité et de tel?
j'ai trébuché sur le merveilleux Non sucking Service Manager , ce qui rend très simple et saine à traiter avec les Services Windows. J'ai trouvé depuis que je je pourrais passer des options à un service installé, je pourrais tout aussi bien sélectionner mon exécutable Python et passer mon script en option.
Je n'ai pas encore essayé cette solution, mais je vais le faire maintenant et mettre à jour ce post tout au long du processus. Je suis également intéressé à utiliser virtualenvs sur Windows, donc je pourrais venir avec un tutoriel tôt ou tard et lien ici.
il y a quelques alternatives pour installer comme un service pratiquement n'importe quel exécutable Windows.
Méthode 1: utiliser instsrv et srvany de rktools.exe
Pour Windows Home Server ou Windows Server 2003 (fonctionne avec WinXP too), le Windows Server 2003 Resource Kit Tools est livré avec des utilitaires qui peuvent être utilisés en tandem pour ce, appelé instsrv.exe et srvany.exe . Voir cet article de Microsoft KB KB137890 pour plus de détails sur la façon d'utiliser ces outils.
Pour Windows Home Server, il y a un grand wrapper facile à utiliser pour ces utilitaires nommés à juste titre " N'importe quel installateur de Service ".
Méthode 2: Utiliser ServiceInstaller pour Windows NT
il existe une autre alternative utilisant ServiceInstaller for Windows NT ( download-able ici ) avec les instructions python disponibles . Contrairement au nom, il fonctionne avec Windows 2000 et Windows XP. Voici quelques instructions pour installer un script python comme service.
installer un script Python
exécuter ServiceInstaller pour créer un nouveau service. (Dans cet exemple, il est supposé que python est installé à 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
après l'installation, ouvrez la commande Services du Panel applet, select et lancez le service PythonTest.
après ma réponse initiale, j'ai remarqué qu'il y avait des questions et réponses étroitement liées déjà affichées sur SO. Voir aussi:
puis-je exécuter un script Python comme un service (sous Windows)? Comment?
Comment faire pour que Windows soit au courant d'un service J'ai écrit en Python?
la façon la plus simple d'y parvenir est d'utiliser la commande native sc.exe:
sc create PythonApp binPath= "C:\Python34\Python.exe --C:\tmp\pythonscript.py"
explication étape par Étape, comment le faire fonctionner :
1-Créez D'abord un fichier python selon le squelette de base mentionné ci-dessus. Et le sauvegarder sur un chemin par exemple: "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-sur cette étape, nous devrions enregistrer notre service.
exécuter l'invite de commande comme administrateur et taper comme:
sc create TestService binpath= "C:\Python36\Python.exe c:\PythonFiles\AppServerSvc.py "DisplayName=" TestService "start =auto
le premier argument de binpath est le chemin de python.exe
second argument de binpath est le chemin de votre fichier python que nous avons déjà créé
ne manquez pas de mettre un espace après chaque " = " signe.
alors si tout va bien, vous devriez voir
[SC] CreateService SUCCESS
maintenant, votre service python est installé comme service windows maintenant. Vous pouvez le voir dans Gestionnaire des services et Registre sous:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TestService
3-Ok maintenant. Vous pouvez commencer votre service sur le gestionnaire de service.
vous pouvez exécuter chaque fichier python qui fournit ce squelette de service.
la manière la plus simple est d'utiliser le: NSSM-the Non-Sucking Service Manager:
1 - faire télécharger sur https://nssm.cc/download
2 - installer le programme python en tant que service: Gagner de l'invite en tant qu'administrateur
c:>nssm.exe install WinService
3 - on nssms console:
chemin: C:\Python27\Python27.exe
répertoire de démarrage: C:\Python27
Arguments: c:\WinService.py
4 - Vérifiez les services créés sur les services.msc
j'ai commencé à héberger comme un service avec pywin32 .
tout allait bien mais j'ai rencontré le problème que le service n'était pas en mesure de démarrer dans les 30 secondes (délai par défaut pour Windows) au démarrage du système. Cela a été critique pour moi parce que le démarrage de Windows a eu lieu simultanément sur plusieurs machines virtuelles hébergées sur une machine physique, et IO charge était énorme. Les messages d'erreur étaient:
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.
je me suis beaucoup battu avec pywin, mais j'ai fini par utiliser NSSM comme il a été proposé dans cette réponse . Il était très facile de migrer.
pysc: Gestionnaire de Contrôle des Services sur Python
exemple de script à exécuter en tant que service tiré 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()
Créer et démarrer le service
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'))
arrêt et suppression du service
import pysc service_name = 'test_xmlrpc_server' pysc.stop(service_name) pysc.delete(service_name)
pip install pysc