Как запустить сценарий 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?
Ответ 4
Самый простой способ добиться этого - использовать встроенную команду sc.exe:
sc create PythonApp binPath= "C:\Python34\Python.exe --C:\tmp\pythonscript.py"
Рекомендации:
- https://technet.microsoft.com/en-us/library/cc990289(v=ws.11).aspx
- При создании сервиса с sc.exe как передать параметры контекста?
Ответ 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