Как запустить сценарий Python как службу в Windows?

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

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

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

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

Ответ 1

Да, вы можете. Я использую библиотеки 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

Ответ 2

Хотя я выделил выбранный ответ пару недель назад, тем временем я больше боролся с этой темой. Похоже, что у вас есть специальная установка на Python и использование специальных модулей для запуска script, поскольку сервис - это просто неправильный путь. Как насчет переносимости и т.д.

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

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

Ответ 3

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

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

Для Windows Home Server или Windows Server 2003 (также работает с WinXP), Windows Server 2003 Resource Kit Tools поставляется с утилит, которые могут для этого используется тандема, называемая instsrv.exe и srvany.exe. Подробнее о том, как использовать эти утилиты, см. В статье Microsoft KB KB137890.

Для Windows Home Server существует большая удобная оболочка для этих утилит с меткой "" Любой установщик услуг".

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

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

Установка Python script

Запустите 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.

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

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

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

Ответ 5

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

1 - скачать на https://nssm.cc/download

2 - установить программу python в качестве службы: Win prompt as admin

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

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

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

Каталог автозагрузки: C:\Python27

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

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

Ответ 6

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

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 создать TestService binpath = "C:\Python36\Python.exe c:\PythonFiles\AppServerSvc.py" DisplayName = "TestService" start = auto

первым аргументом binpath является путь файла python.exe

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

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

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

[SC] Усиление CreateService

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

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TestService

3- Хорошо. Вы можете начать свою службу в сервис-менеджере.

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

Ответ 7

Я начал хостинг как сервис с 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, как было предложено в этом ответе. Было очень легко перейти на него.

Ответ 8

nssm в Python 3+

(Я преобразовал свой .py файл в .exe с помощью pyinstaller)

NSSM: как уже было сказано

  • запустите nssm install {ServiceName}
  • На консоли NSSM:

    путь: путь\к\вашему\program.exe

    Каталог запуска: путь\к\your\#same в качестве пути, но без вашей программы .exe

    Аргументы: пусто

Ответ 9

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

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

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

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

Ответ 10

Для тех, кто хочет создать сервис в 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 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)

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

Ответ 11

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

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