Демонизирайте и мащабирайте вашите Python приложения

В част първа от тази статия се съсредоточихме върху създаването на демон процеси с помощта на специфични за Unix пакети.



Във втора част от тази поредица се потапяме дълбоко в това как можем да направим същото на машина с Windows, като използваме еквивалентните услуги на Windows.

PyWin32 ще бъде основният пакет на Python, който ще служи като основна библиотека, която ни позволява да създаваме услуги на Windows, които имитират Unix демони.

Пакетът PyWin32 е обвивка за специфична за Windows функционалност и C API. Тази помощна програма е създадена от Марк Хамънд като добавка, която включва Win32 API, COM поддръжка и разширения PythonWin.

Благодарение на тази удобна библиотека имаме достъп за програмен контрол на Windows чрез Win32 API.

Нека да преминем направо към създаването на нашата първа услуга на Python, която прави точно същото, което правеше нашият оригинален демон код. Трябва да сме сигурни, че сме инсталирали PyWin32. За да направите това, изпълнете следната команда:

pip install pywin32

Нека създадем базов сервизен клас, който разширява PyWin32, win32serviceutil.ServiceFramework, така че всички наши дъщерни Windows услуги да могат да наследяват от него.

Всички услуги на Python Windows ще подкласират класа win32serviceutil.ServiceFramework.

Класът PyWin32 има редица методи по подразбиране и помощни методи, за да улесни писането на услуги в Python. Например функции, необходими за стартиране/спиране/инсталиране/премахване на услуга; функциите, които обикновено се използват от Service Control Manager (SCM).

Нека създадем персонализиран дъщерен Windows сервизен клас, който разширява нашия базов клас, състоящ се от същата логика, която видяхме в първа част на тази статия, т.е. нашия фиктивен нов агрегатор на емисии.

Тествайте услугата Windows

За да сте сигурни, че вашият Python скрипт работи добре, първо го изпълнете в режим на отстраняване на грешки.

c:\Users\User\Documents>python service.py install
Installing NewsApiService Service
Installing service NewsApiService
Service installed

Последвано от изпълнение на режима за отстраняване на грешки:

c:\Users\User\Documents>python service.py debug
Installing OptimizationModelService Service
Debugging service NewsApiService - press Ctrl+C to stop.
Info 0x40001002 - The NewsApiService service has started.

Ако командите за инсталиране и отстраняване на грешки работят според очакванията, продължете и тествайте изпълнението на вашата услуга ръчно, като отидете до контролния панел на услугата на Windows.

Щракнете с десния бутон върху бутона Старт, за да отворите менюто Win. Изберете Изпълни. Това отваря полето Run. Сега въведете services.msc в него и натиснете Enter, за да отворите Services Manager.

Потърсете услугата Windows, която сте създали, както е показано на изображението по-долу.

Щракнете с десния бутон върху услугата OptimizationModel Winservice и щракнете върху старт. Това трябва да позволи на услугата да започне да се изпълнява във фонов режим.

Услугата Python не работи?

Това е така, защото всичко работи по различен начин в Windows, ако не е ориентирано към Windows.

Това са няколко проблема, които могат да се случат. Нещо, което твърде често се среща при работа с услуги на Microsoft Windows, като например проблеми с разрешенията, липсващи DLL файлове.

За тези от вас, които разработват на машини с Windows, сигурен съм, че това е обичайно ежедневие и понякога се очаква, преди кодът ви да се изпълни правилно. Това е, ако работите извън Docker.

Нека се разходим през някои от проблемите и възможните решения.

1. Грешка: Достъпът е отказан, когато се опитате да инсталирате вашата услуга Python

C:\Users\User\Documents> python service.py install
Installing NewsApiService Service
Installing service NewsApiService
Error installing service: Access is denied. (5)

За да разрешите горната грешка, стартирайте своя скрипт чрез командния ред, като стартирате като администратор. Натиснете Windows+R, за да отворите полето Run.

Въведете името на CMD командата. След като въведете командата си, натиснете Ctrl+Shift+Enter, за да я изпълните с администраторски привилегии. Натискането на Enter изпълнява командата като нормален потребител.

Ако изпълнявате кода си през вградените терминални прозорци, като използвате IDE като VS Code или PyCharm, щракнете с десния бутон → стартирайте като администратор → трябва да сте готови към този момент.

2. Python Windows услуга „Грешка при стартиране на услуга: Услугата не отговори навреме на заявката за стартиране или контрол“

Тази грешка може да бъде причинена от множество проблеми.

Липсва път на Python

Всеки процес има блок за среда, който съдържа набор от променливи на средата и техните стойности.

Има два типа променливи на средата:

  1. Променливи на потребителската среда (зададени за всеки потребител).
  2. Променливи на системната среда (зададени за всеки).

Системните услуги на Windows работят като глобални. Следователно, вашият Python път трябва също да съществува в променливите на вашата системна среда, които имат предимство пред дефинираните от потребителя променливи по отношение на променливата на средата PATH.

Липсващи типове pywin

Не забравяйте да добавите файла pywintypes към C:\Program Files\Python38\Lib\site-packages\win32\pywintypes38.dll.

Моля, имайте предвид, че „38“ е версията на вашата инсталация на Python, която зависи от версията, която използвате.

Pywintypes могат да бъдат разположени в C:\Program Files\Python38\Lib\site-packages\pywin32_system32\pywintypes38.dll.

Разпространение на вашите Windows услуги

Нека модифицираме нашия код, така че да можем да имаме множество екземпляри на нашия агрегат за новини, работещи по разпределен начин. Това е за илюстрация, тъй като нашият скрипт не прави много.

Изпълнението на горния код инсталира три услуги от един и същи тип, които могат да се изпълняват паралелно чрез менюто за услуги на Windows.

C:\Users\User\Documents> python .\service.py install
Installing NewsApiService0 Service
Installing service NewsApiService0
Service installed
Installing NewsApiService1 Service
Installing service NewsApiService1
Service installed
Installing NewsApiService2 Service
Installing service NewsApiService2
Service installed

Това генерира следните изходни файлове с уникален PID, свързан с всяка услуга.

Можем да направим нещата още една крачка напред и да автоматизираме процеса, така че да можем програмно да стартираме и спираме услугите на Windows в нашия Python код, както е показано по-долу.

Деинсталиране на Python Windows Service

По-долу е подходът на командния ред за премахване на услуга на Windows, като се използва помощната програма SC на командния ред на Windows Service Controller.

Като алтернатива, ако искате да го направите програмно, можете да извикате функцията remove_service.

def remove_service(service_name):

Sc [‹ServerName›] изтрийте [‹ServiceName›].

c:\Users\User\Documents>sc delete "NewsApiService"
[SC] DeleteService SUCCESS

Последни мисли

Изпълнението на фонови задачи с помощта на демони и услуги на Windows има своите предимства. Има много малко за конфигуриране, за да стартирате програмите си, като се възползвате от общия брой ядра, които имате на вашата машина.

С няколко реда код можете да изградите фонови работници, които могат да обработват данни и да извършват сложни изчисления, без да въвеждате рамки в микса.

Надявам се, че сте намерили материала за полезен.