Как запустить скрипт Python как службу в Windows? - PullRequest
236 голосов
/ 28 августа 2008

Я делаю набросок архитектуры для набора программ, которые совместно используют различные взаимосвязанные объекты, хранящиеся в базе данных. Я хочу, чтобы одна из программ работала в качестве службы, предоставляющей интерфейс более высокого уровня для операций с этими объектами, а другие программы для доступа к объектам через эту службу.

В настоящее время я стремлюсь к Python и инфраструктуре Django в качестве технологий для реализации этого сервиса. Я почти уверен, что понимаю, как демонизировать программу Python в Linux. Однако это необязательный элемент спецификации, который система должна поддерживать Windows. У меня мало опыта в программировании Windows и совсем нет опыта работы со службами Windows.

Можно ли запускать программы на Python как службу Windows (т.е. запускать ее автоматически без входа пользователя)? Мне не обязательно будет реализовывать эту часть, но мне нужно приблизительное представление о том, как она будет сделано для того, чтобы решить, следует ли проектировать по этим направлениям.

Редактировать: Спасибо за ответы на все вопросы, они достаточно полны. Я хотел бы знать еще одну вещь: Как Windows знает о моем сервисе? Могу ли я управлять им с помощью собственных утилит Windows? Что эквивалентно размещению сценария запуска / остановки в /etc/init.d?

Ответы [ 10 ]

236 голосов
/ 28 августа 2008

Да, вы можете. Я делаю это с помощью библиотек pythoncom, которые поставляются с ActivePython или могут быть установлены с pywin32 (расширения Python для Windows).

Это базовый скелет для простого обслуживания:

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)

Ваш код будет идти в методе main() - обычно с неким бесконечным циклом, который может быть прерван проверкой флага, который вы устанавливаете в методе SvcStop

34 голосов
/ 28 июля 2014

Хотя я проголосовал за выбранный ответ пару недель назад, тем временем я боролся с этой темой гораздо больше. Такое чувство, что иметь специальную установку Python и использовать специальные модули для запуска скрипта как сервиса - просто неправильный путь. А как насчет портативности и тому подобное?

Я наткнулся на замечательного Непососавшего Service Manager , что сделало работу с Windows Services действительно простой и разумной. Я подумал, что поскольку я мог передавать параметры установленной службе, я мог бы также выбрать свой исполняемый файл Python и передать свой сценарий в качестве опции.

Я еще не пробовал это решение, но сделаю это прямо сейчас и обновлю этот пост по ходу процесса. Я также заинтересован в использовании virtualenvs в Windows, поэтому, возможно, рано или поздно я приду к учебнику и сошлюсь на него здесь.

24 голосов
/ 28 февраля 2009

Существует пара альтернатив для установки в качестве службы практически любого исполняемого файла Windows.

Способ 1: использовать instsrv и srvany из rktools.exe

Для Windows Home Server или Windows Server 2003 (работает также с WinXP), Средства для набора ресурсов Windows Server 2003 поставляются с утилитами, которые могут использоваться для этой цели, которые называются instsrv.exe. и srvany.exe . См. Эту статью Microsoft KB KB137890 для получения подробной информации о том, как использовать эти утилиты.

Для Windows Home Server есть отличная удобная оболочка для этих утилит, названная метко " Any Service Installer ".

Способ 2. Использование ServiceInstaller для Windows NT

Существует еще одна альтернатива, использующая ServiceInstaller для Windows NT ( доступна для загрузки здесь ) с доступными инструкциями Python . Вопреки названию, он работает как с Windows 2000, так и с Windows XP. Вот несколько инструкций по установке скрипта Python в качестве службы.

Установка скрипта Python

Запустите ServiceInstaller, чтобы создать новый оказание услуг. (В этом примере это Предполагается, что Python установлен на 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

После установки откройте Control Апплет Panel Services, выберите и запустите сервис PythonTest.

После моего первоначального ответа я заметил, что на SO уже размещены тесно связанные вопросы и ответы. Смотри также:

Можно ли запустить скрипт Python как службу (в Windows)? Как?

Как я могу информировать Windows о службе, написанной на Python?

23 голосов
/ 07 декабря 2016

Самый простой способ добиться этого - использовать встроенную команду 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. При создании сервиса с sc.exe как передать контекстные параметры?
19 голосов
/ 27 сентября 2017

Самый простой способ - использовать: NSSM - диспетчер неосасывающих услуг:

1 - сделать загрузку на https://nssm.cc/download

2 - установить программу python как службу: Win приглашение от имени администратора

c:> nssm.exe установить WinService

3 - На консоли NSSM:

путь: C: \ Python27 \ Python27.exe

Каталог запуска: C: \ Python27

Аргументы: c: \ WinService.py

4 - проверить созданные сервисы на services.msc

12 голосов
/ 29 июня 2017

Пошаговое объяснение, как заставить это работать:

1- Сначала создайте файл Python в соответствии с базовым скелетом, упомянутым выше. И сохраните его по пути, например: "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 - На этом шаге мы должны зарегистрировать наш сервис.

Запустите командную строку как Администратор и введите как:

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

первый аргумент binpath - это путь к python.exe

второй аргумент binpath - это путь к вашему файлу Python , который мы уже создали

Не пропустите, чтобы после каждого знака " = " ставить один пробел.

Тогда, если все в порядке, вы должны увидеть

[SC] CreateService SUCCESS

Теперь ваша служба Python установлена ​​как служба Windows. Вы можете увидеть это в Service Manager и реестре под:

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ TestService

3- Хорошо, теперь. Вы можете запустить свой сервис на сервис менеджера.

Вы можете выполнить каждый файл python, который предоставляет этот каркас службы.

2 голосов
/ 12 октября 2018

Я начал хостинг как сервис с pywin32 .

Все было хорошо, но я столкнулся с проблемой, что служба не может запуститься в течение 30 секунд (время ожидания по умолчанию для Windows) при запуске системы. Это было очень важно для меня, потому что запуск Windows происходил одновременно на нескольких виртуальных машинах, размещенных на одной физической машине, и нагрузка ввода-вывода была огромной. Сообщения об ошибках были:

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.

Я много боролся с pywin, но в итоге использовал NSSM, как было предложено в этом ответе . Мигрировать было очень легко.

0 голосов
/ 29 мая 2019

Для тех, кто хочет создать сервис в VENV или Pycharm !!!!!!!

После прочтения всех ответов и создания сценариев, если вы можете запустить python service.py install и python service.py debug, но python service.py start не имеет ответа.

Возможно, это связано с проблемой venv, потому что служба Windows запускает вашу службу с помощью exec PROJECT\venv\Lib\site-packages\win32\pythonservice.exe.

Вы можете использовать powershell или cmd, чтобы протестировать свой сервис и выяснить подробности ошибки.

PS C:\Users\oraant> E:

PS E:\> cd \Software\PythonService\venv\Lib\site-packages\win32

PS E:\Software\PythonService\venv\Lib\site-packages\win32> .\pythonservice.exe -debug ttttt
Debugging service ttttt - press Ctrl+C to stop.
Error 0xC0000004 - Python could not import the service's module

Traceback (most recent call last):
  File "E:\Software\PythonService\my_service.py", line 2, in <module>
    import win32serviceutil
ModuleNotFoundError: No module named 'win32serviceutil'

(null): (null)

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

0 голосов
/ 10 ноября 2018

Принятый ответ с использованием win32serviceutil работает, но сложен и усложняет отладку и изменения. далеко проще в использовании NSSM ( Менеджер не сосущих услуг) . Вы пишете и удобно отлаживаете обычную программу на Python, и когда она наконец работает, вы используете NSSM, чтобы установить ее как службу менее чем за минуту:

В командной строке с повышенными привилегиями (admin) вы запускаете nssm.exe install NameOfYourService и вводите следующие параметры:

  • путь : (путь к python.exe, например C:\Python27\Python.exe)
  • Аргументы : (путь к вашему скрипту Python, например, c:\path\to\program.py)

Кстати, если ваша программа печатает полезные сообщения, которые вы хотите сохранить в файле журнала, NSSM также может обработать это и многое другое для вас.

0 голосов
/ 03 марта 2017

pysc: Диспетчер управления службами на Python

Пример сценария для запуска в качестве службы взято с 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()

Создание и запуск службы

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

Остановка и удаление службы

import pysc

service_name = 'test_xmlrpc_server'

pysc.stop(service_name)
pysc.delete(service_name)
pip install pysc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...