Возникла у меня давеча необходимость (а может просто непреодолимое желание
) сделать парочку Windows служб из Python-скриптов. Немного порывшись в «интернетах» я обнаружил, что осуществить это не так уж и сложно и, более того, способов существует аж.. два. Итак, хозяйке на заметку...
Рецепт первый. Для непривередливых
Этот рецепт позволяет приготовить Windows службу не только из Python скрипта, но и вообще из любой программы. Для приготовления понадобятся:
- Утилиты srvany.exe и instsrv.exe (необязательно, но об этом ниже).Найти их можно в пакете Windows Server 2003 Resource Kit Tools. Устанавливать все утилиты необязательно, можно просто распаковать дистрибутив (например, при помощи 7Zip) и скопировать из него нужные файлы.
- Собственно Python-скрипт, в котором необходимые вам действия выполняются в бесконечном цикле (либо, как было сказано выше, любое другое приложение также крутящееся в бесконечном цикле)
- Notepad

Если все ингредиенты присутствуют, то дело остается за малым — смешать, встряхнуть, употребить соединить все вместе, для чего делаем следующее:
- Выполняем в командной строке
instsrv <Service Name> "C:\Program Files\Custom Service\srvany.exe"
где <Service Name> – желаемое имя сервиса, т.е. именно так он будет называться в оснастке Services
Внимание, путь к srvany.exe нужно указывать полностью!Как было отмечено выше, использовать instserv.exe необязательно, вместо него можно воспользоваться стандартной утилитой SC. В случае использования этой утилиты в командной строке необходимо выполнить следующее:
sc create <Service Name> binpath= "C:\Program Files\Custom Service\srvany.exe"
где <Service Name> – желаемое имя сервиса.
Внимание! Путь к srvany.exe нужно указывать полностью. После binpath= обязательно должен быть пробел, иначе ничего работать не будет! - Создаем reg файл следующего содержания:
REGEDIT4 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<Service Name>\Parameters] ; Путь к интерпретатору pythonw.exe "Application"="C:\\Python26\\pythonw.exe" ; Путь к папке в которой находится необходимый скрипт "AppDirectory"="C:\\Program Files\\Custom Service" ; Собственно, путь к самому скрипту "AppParameters"="C:\\Program Files\\Custom Service\\custom_script.py"Внимание! Слеши обязательно должны быть двойными.
В случае, если вы создаете службу не из Python-скрипта, то ключ Application должен содержать путь к приложению, которое вы хотите запускать как Windows Service, а AppDirectory и AppParametrs рабочую директорию и параметры его запуска соответственно. - Добавляем ключи из созданного файла в реестр
- Открываем оснастку Services и запускаем свежеиспеченную службу, либо выполняем в командной строке:
sc start <Service Name>
Рецепт второй. Для гурманов
Почему для гурманов? Да потому, что этот рецепт, во-первых, подразумевает приготовление службы без использования сторонних утилит, во-вторых, реализуется при помощи Windows API со всеми вытекающими (т.е. позволит, например, выполнить необходимые действия при остановке службы или записывать все что вам необходимо в Event Log). Для приготовления понадобятся:
- PyWin32 (скажу по-секрету, что пример реализации службы присутствует в демо-скриптах этого пакета, просто не все их смотрели
) - hands.dll

Когда все необходимые приготовления будут закончены, можно приступать к написанию кода. Выглядеть он должен приблизительно вот так:
- # -*- coding: utf-8 -*-
- #! /usr/bin/env python
- import win32serviceutil
- import win32service
- import win32event
- import servicemanager
- class AppServerSvc (win32serviceutil.ServiceFramework):
- _svc_name_ = "DummyService"
- _svc_display_name_ = "Dummy Service"
- _svc_description_ = "Dummy Service Description"
- def __init__(self,args):
- win32serviceutil.ServiceFramework.__init__(self,args)
- self.hWaitStop = win32event.CreateEvent(None,0,0,None)
- self.hWaitResume = win32event.CreateEvent(None, 0, 0, None)
- self.timeout = 10000 #Пауза между выполнением основного цикла службы в миллисекундах
- self.resumeTimeout = 1000
- self._paused = False
- def SvcStop(self):
- self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
- win32event.SetEvent(self.hWaitStop)
- servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
- servicemanager.PYS_SERVICE_STOPPED,
- (self._svc_name_, ''))
- def SvcPause(self):
- self.ReportServiceStatus(win32service.SERVICE_PAUSE_PENDING)
- self._paused = True
- self.ReportServiceStatus(win32service.SERVICE_PAUSED)
- servicemanager.LogInfoMsg("The %s service has paused." % (self._svc_name_, ))
- def SvcContinue(self):
- self.ReportServiceStatus(win32service.SERVICE_CONTINUE_PENDING)
- win32event.SetEvent(self.hWaitResume)
- self.ReportServiceStatus(win32service.SERVICE_RUNNING)
- servicemanager.LogInfoMsg("The %s service has resumed." % (self._svc_name_, ))
- def SvcDoRun(self):
- servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
- servicemanager.PYS_SERVICE_STARTED,
- (self._svc_name_,''))
- self.main()
- #В этом методе реализовываем нашу службу
- def main(self):
- #Здесь выполняем необходимые действия при старте службы
- servicemanager.LogInfoMsg("Hello! I'm a Dummy Service.")
- while True:
- #Здесь должен находиться основной код сервиса
- servicemanager.LogInfoMsg("I'm still here.")
- #Проверяем не поступила ли команда завершения работы службы
- rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout)
- if rc == win32event.WAIT_OBJECT_0:
- #Здесь выполняем необходимые действия при остановке службы
- servicemanager.LogInfoMsg("Bye!")
- break
- #Здесь выполняем необходимые действия при приостановке службы
- if self._paused:
- servicemanager.LogInfoMsg("I'm paused... Keep waiting...")
- #Приостановка работы службы
- while self._paused:
- #Проверям не поступила ли команда возобновления работы службы
- rc = win32event.WaitForSingleObject(self.hWaitResume, self.resumeTimeout)
- if rc == win32event.WAIT_OBJECT_0:
- self._paused = False
- #Здесь выполняем необходимые действия при возобновлении работы службы
- servicemanager.LogInfoMsg("Yeah! Let's continue!")
- break
- if __name__ == '__main__':
- win32serviceutil.HandleCommandLine(AppServerSvc)
Как только с написанием кода будет покончено, сохраняем службу в обычный питоновский файл, например, myservice.py и запускаем его из командной строки следующим образом:
myservice.py install
Служба готова. Можно пользоваться.










- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии и скачивать файлы



Последние комментарии
4 дня 6 часов назад
1 неделя 4 дня назад
1 неделя 4 дня назад
3 недели 4 дня назад
6 недель 3 дня назад
7 недель 2 дня назад
7 недель 3 дня назад
7 недель 3 дня назад
7 недель 6 дней назад
10 недель 4 дня назад