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?
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
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.
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?
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"
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.
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
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.
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
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