Jak uruchomić skrypt Pythona jako usługę w systemie Windows?

Szkicuję architekturę zestawu programów, które dzielą różne powiązane ze sobą obiekty przechowywane w bazie danych. Chcę, aby jeden z programów działał jako usługa, która zapewnia interfejs wyższego poziomu dla operacji na tych obiektach, a inne programy miały dostęp do obiektów za pośrednictwem tej usługi.

Obecnie poszukuję Pythona i frameworka Django jako technologii do implementacji tej usługi. Jestem pewien, że wymyśliłem, jak daemonizować program Pythona w Linux. Jest to jednak opcjonalny element specyfikacji, który system powinien obsługiwać Windows. Mam małe doświadczenie z programowaniem Windows i nie mam żadnego doświadczenia z usługami Windows.

Czy można uruchamiać programy Pythona jako usługę Windows (tzn. uruchamiać je automatycznie bez logowania użytkownika)? niekoniecznie będę musiał wdrożyć tę część, ale potrzebuję przybliżonego pomysłu, jak to będzie zrobione, aby zdecydować, czy projektować zgodnie z tymi zasadami.

Edit: dzięki za wszystkie odpowiedzi do tej pory są dość wyczerpujące. Chciałbym wiedzieć jeszcze jedno: skąd Windows wie o mojej usłudze? Czy Mogę nim zarządzać za pomocą natywnych narzędzi Windows? co jest równoznaczne z umieszczeniem skryptu start/stop w /etc / init.d?

Author: Undo, 2008-08-28

8 answers

Tak, możesz. Robię to za pomocą bibliotek pythoncom, które są dołączone do ActivePythonlub mogą być zainstalowane z pywin32 (Python for Windows extensions).

Jest to podstawowy szkielet dla prostej usługi:

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)

Twój kod pójdzie w metodzie main() - Zwykle z jakąś nieskończoną pętlą, która może zostać przerwana przez sprawdzenie flagi, którą ustawisz w metodzie SvcStop

 224
Author: Ricardo Reyes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-14 04:26:45

Chociaż kilka tygodni temu podniosłem wybraną odpowiedź, w międzyczasie zmagałem się o wiele bardziej z tym tematem. Wydaje się, że posiadanie specjalnej instalacji Pythona i używanie specjalnych modułów do uruchamiania skryptu jako usługi jest po prostu złym sposobem. A co z przenośnością i tym podobne?

Natknąłem się na wspaniały Non-sucking Service Manager , który sprawił, że obsługa usług Windows była naprawdę prosta i rozsądna. Pomyślałem, że skoro mogę przekazać opcje do zainstalowanego service, mogę równie dobrze wybrać Mój program wykonywalny Python i przekazać mój skrypt jako opcję.

Nie próbowałem jeszcze tego rozwiązania, ale zrobię to teraz i zaktualizuję ten post wzdłuż procesu. Jestem również zainteresowany używaniem virtualenvs na Windows, więc prędzej czy później mogę wymyślić tutorial i link do niego tutaj.

 31
Author: mknaf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-28 13:41:31

Istnieje kilka alternatyw do instalacji jako usługi praktycznie dowolnego pliku wykonywalnego Windows.

Metoda 1: Użyj instsrv i srvany z rktools.exe

Dla Windows Home Server lub Windows Server 2003 (działa również z WinXP), Windows Server 2003 Resource Kit Tools zawiera narzędzia, które mogą być używane w tym celu razem, o nazwie instsrv.exe i srvany.exe . Zobacz ten artykuł Microsoft KB KB137890 aby dowiedzieć się, jak z nich korzystać utils.

Dla Windows Home Server, istnieje wielki przyjazny dla użytkownika wrapper dla tych narzędzi o nazwie trafnie " Any Service Installer ".

Metoda 2: Użyj ServiceInstaller Dla Windows NT

Istnieje inna alternatywa dla ServiceInstaller Dla Windows NT (Pobierz-able tutaj ) z instrukcjami Pythona dostępnymi . Wbrew nazwie działa zarówno z Windows 2000, jak i Windows XP. Oto kilka instrukcji, jak zainstaluj skrypt Pythona jako usługę.

Instalacja skryptu Pythona

Uruchom ServiceInstaller, aby utworzyć nowy obsługa. (W tym przykładzie jest zakłada, że python jest zainstalowany na 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

Po zainstalowaniu otwórz kontrolkę Aplet usług panelu, wybierz i uruchom usługę PythonTest.

Po mojej wstępnej odpowiedzi, zauważyłem, że były ściśle związane Q&A już opublikowane na SO. Zobacz też:

Can Uruchamiam skrypt Pythona jako usługę (w systemie Windows)? Jak?

Jak mogę poinformować System Windows o usłudze napisanej w Pythonie?

 24
Author: popcnt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:01

Najprostszym sposobem na osiągnięcie tego jest użycie natywnego polecenia 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. tworzenie serwisu z sc.exe; jak przekazać w parametrach kontekstowych
 15
Author: pyOwner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:50

Wyjaśnienie krok po kroku jak to działa:

1 - najpierw Utwórz plik Pythona zgodnie z podstawowym szkieletem wspomnianym powyżej. I zapisać go do ścieżki na przykład : "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-na tym kroku powinniśmy zarejestrować nasz serwis.

Uruchom wiersz polecenia jako administrator i wpisz jako:

Sc create testservice binpath= "C:\Python36\Python.exe c:\PythonFiles\AppServerSvc.py "DisplayName=" TestService " start= auto

Pierwszy argument binpath jest ścieżką Pythona.exe

Drugi argument binpath jest ścieżką Twojego pliku Pythona , który już stworzyliśmy

Nie przegap, że powinieneś umieścić jedno miejsce po każdym "=" podpisz.

Wtedy jeśli wszystko jest w porządku, powinieneś zobaczyć

[SC] CreateService SUCCESS

Teraz Twoja usługa Pythona jest zainstalowana jako usługa windows. Można to zobaczyć w Kierownik serwisu i rejestr pod :

HKEY_LOCAL_MACHINE \ SYSTEM\CurrentControlSet\Services \ TestService

3-Ok teraz. Możesz uruchomić usługę na service manager.

Możesz wykonać każdy plik Pythona, który udostępnia ten szkielet usługi.

 8
Author: Seckin Sanli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-29 08:37:26

Najprostszym sposobem jest użycie: NSSM-Non-Sucking Service Manager:

1 - Pobierz na https://nssm.cc/download

2 - Zainstaluj program python jako usługę: Win prompt jako admin

C: > nssm.exe install WinService

3 - na konsoli NSSMs:

Ścieżka: C:\Python27\Python27.exe

Katalog startowy: C:\Python27

Argumenty: c:\WinService.py

4 - Sprawdź utworzone usługi na usługach.msc

 8
Author: Adriano R P L,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-27 14:05:43

Zacząłem hosting jako usługa z pywin32 .

Wszystko było dobrze, ale napotkałem problem, że usługa nie była w stanie uruchomić się w ciągu 30 sekund (domyślny timeout Dla Windows) przy starcie systemu. Było to dla mnie krytyczne, ponieważ uruchamianie systemu Windows odbywało się jednocześnie na kilku maszynach wirtualnych hostowanych na jednej maszynie fizycznej, a obciążenie IO było ogromne. Komunikaty o błędach:

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.

Dużo walczyłem z pywinem, ale skończyło się na używaniu NSSM jako została zaproponowana w tej odpowiedzi . Migracja do niego była bardzo łatwa.

 0
Author: flam3,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-12 13:07:47

Pysc: Service Control Manager w Pythonie

Przykładowy skrypt uruchamiany jako usługa wzięty z 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()

Utwórz i uruchom serwis

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

Zatrzymaj i usuń usługę

import pysc

service_name = 'test_xmlrpc_server'

pysc.stop(service_name)
pysc.delete(service_name)
pip install pysc
 -2
Author: Seliverstov Maksim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-08 14:20:32