Запустить python как сервис windows

Пройдите тест, узнайте какой профессии подходите

Работать самостоятельно и не зависеть от других

Работать в команде и рассчитывать на помощь коллег

Организовывать и контролировать процесс работы

Быстрый ответ

Для того чтобы Python-скрипт мог работать в роли службы Windows, рекомендуется использовать библиотеку pywin32. Создайте класс службы, который будет унаследован от win32serviceutil.ServiceFramework, а затем переопределите методы SvcDoRun и SvcStop для управления запуском и остановкой службы. Установка и управление службой происходит через командную строку. Пример кода представлен ниже:

Для установки и запуска службы воспользуйтесь следующими командами:

Данный метод позволит вам работать со скриптом Python как с службой Windows.

Кинга Идем в IT: пошаговый план для смены профессии

Расширение функционала вашей службы

Использование NSSM для упрощённого управления службами

NSSM (Non-Sucking Service Manager) предлагает комфортный графический интерфейс для управления службами, облегчая настройку использования скриптов и переменных среды.

Регистрация вашей службы с помощью sc.exe

Можно зарегистрировать ваш скрипт как службу, используя команду sc.exe:

Применение Python и Django для управления службами

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

Использование опыта работы с демонами в Linux

Если у вас имеется опыт работы с демонами в Linux, то вы усвоите создание служб для Windows быстрее, несмотря на специфику реализации в этих системах.

Визуализация

Представьте себе Python-скрипт, превращающийся в службу Windows, как робот (🤖), которы работает в автономном режиме:

Изначально Python-скрипт — это просто набор команд (📜), но после аккуратной настройки (🔧👨‍🔧), он превращается в полноценно функционирующую службу (🤖).

Решение возникающих проблем

Журналирование работы службы и обработка ошибок

Servicemanager поможет вести журнал работы службы и адекватно обрабатывать возникающие ошибки, давая полное представление о функционировании службы и возможных проблемах.

Управление переменными окружения

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

Управление зависимостями

Работа службы может требовать конкретные версии библиотек или внешние модули Python. Для этого используются виртуальные среды и PyInstaller, который создаёт исполняемые файлы со всеми необходимыми зависимостями.

Продвинутое управление службой

Масштабирование службы

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

Тонкая настройка службы через реестр

Можно детально настроить поведение службы на уровне реестра Windows по адресу HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services.

Бесперебойные обновления и поддержка служб

Обеспечивайте возможности «горячего» обновления и «мягкого» завершения работы службы для сокращения времени простоя. Нужно продумать надежный механизм обновлений, который позволит внедрять новые версии службы без ручного вмешательства.

Полезные материалы

  1. NSSM – the Non-Sucking Service Manager — инструмент для простого управления Python-службами.
  2. Как запустить скрипт Python как службу в Windows на Stack Overflow — обсуждения и решения от сообщества разработчиков.
  3. Полный пример службы от Microsoft — официальные рекомендации по созданию служб Windows.
  4. Руководство по PyInstaller — создание автономных исполняемых файлов из Python-скриптов.
  5. Планировщик задач для разработчиков от Microsoft — использование Планировщика задач Windows для автоматизации Python-скриптов.
  6. Supervisor: Система контроля процессов — мониторинг и контроль над продолжительными службами на Python.

The web is a living, breathing organism – it constantly adapts and changes. In this dynamic environment, gathering time-sensitive data such as E-commerce listings only once is useless as it quickly becomes obsolete. To be competitive, you must keep your data fresh and run your web scraping scripts repeatedly and regularly.

The easiest way is to run a script in the background. In other words, run it as a service. Fortunately, no matter the operating system in use – Linux or Windows – you have great tools at your disposal. In today’s guide, we’ll demonstrate how to run a Python script on a server in just a few simple steps.

For your convenience, we also prepared this tutorial in a video format:

Preparing a Python script for Linux

In this article, information from a list of book URLs will be scraped. When the process reaches the end of the list, it loops over and refreshes the data again and again.

First, make a request and retrieve the HTML content of a page. Use the Requests module to do so:

urls = [
'https://books.toscrape.com/catalogue/sapiens-a-brief-history-of-humankind_996/index.html',
'https://books.toscrape.com/catalogue/shakespeares-sonnets_989/index.html',
'https://books.toscrape.com/catalogue/sharp-objects_997/index.html',
]

index = 0
while True:
    url = urls[index % len(urls)]
    index += 1

    print('Scraping url', url)
    response = requests.get(url)

Once the content is retrieved, parse it using the Beautiful Soup library:

soup = BeautifulSoup(response.content, 'html.parser')
book_name = soup.select_one('.product_main').h1.text
rows = soup.select('.table.table-striped tr')
product_info = {row.th.text: row.td.text for row in rows}

Make sure your data directory-to-be already exists, and then save book information there in JSON format.

Protip: make sure to use the pathlib module to automatically convert Python path separators into a format compatible with both Windows and Linux systems.

data_folder = Path('./data')
data_folder.mkdir(parents=True, exist_ok=True)

json_file_name = re.sub('[: ]', '-', book_name)
json_file_path = data_folder / f'{json_file_name}.json'
with open(json_file_path, 'w') as book_file:
    json.dump(product_info, book_file)

Since this script is long-running and never exits, you must also handle any requests from the operating system attempting to shut down the script. This way, you can finish the current iteration before exiting. To do so, you can define a class that handles the operating system signals:

class SignalHandler:
    shutdown_requested = False

    def __init__(self):
        signal.signal(signal.SIGINT, self.request_shutdown)
        signal.signal(signal.SIGTERM, self.request_shutdown)

    def request_shutdown(self, *args):
        print('Request to shutdown received, stopping')
        self.shutdown_requested = True

    def can_run(self):
        return not self.shutdown_requested

Instead of having a loop condition that never changes (while True), you can ask the newly built SignalHandler whether any shutdown signals have been received:

signal_handler = SignalHandler()

# ...

while signal_handler.can_run():
    # run the code only if you don't need to exit

Here’s the code so far:

import json
import re
import signal
from pathlib import Path

import requests
from bs4 import BeautifulSoup

class SignalHandler:
    shutdown_requested = False

    def __init__(self):
        signal.signal(signal.SIGINT, self.request_shutdown)
        signal.signal(signal.SIGTERM, self.request_shutdown)

    def request_shutdown(self, *args):
        print('Request to shutdown received, stopping')
        self.shutdown_requested = True

    def can_run(self):
        return not self.shutdown_requested


signal_handler = SignalHandler()
urls = [
    'https://books.toscrape.com/catalogue/sapiens-a-brief-history-of-humankind_996/index.html',
    'https://books.toscrape.com/catalogue/shakespeares-sonnets_989/index.html',
    'https://books.toscrape.com/catalogue/sharp-objects_997/index.html',
]

index = 0
while signal_handler.can_run():
    url = urls[index % len(urls)]
    index += 1

    print('Scraping url', url)
    response = requests.get(url)

    soup = BeautifulSoup(response.content, 'html.parser')
    book_name = soup.select_one('.product_main').h1.text
    rows = soup.select('.table.table-striped tr')
    product_info = {row.th.text: row.td.text for row in rows}

    data_folder = Path('./data')
    data_folder.mkdir(parents=True, exist_ok=True)

    json_file_name = re.sub('[\': ]', '-', book_name)
    json_file_path = data_folder / f'{json_file_name}.json'
    with open(json_file_path, 'w') as book_file:
        json.dump(product_info, book_file)

The script will refresh JSON files with newly collected book information.

Running a Linux daemon

If you’re wondering how to run Python script on server in Linux, there are multiple ways to do it on startup. Many distributions have built-in GUI tools for such purposes.

Let’s use one of the most popular distributions, Linux Mint, as an example. It uses a desktop environment called Cinnamon that provides a startup application utility.

System settings

System settings

It allows you to add your script and specify a startup delay.

Adding a script

Adding a script

However, this approach doesn’t provide more control over the script. For example, what happens when you need to restart it?

This is where systemd comes in. Systemd is a service manager that allows you to manage user processes using easy-to-read configuration files.

To use systemd, let’s first create a file in the /etc/systemd/system directory:

cd /etc/systemd/system
touch book-scraper.service

Add the following content to the book-scraper.service file using your favorite editor:

[Unit]
Description=A script for scraping the book information
After=syslog.target network.target

[Service]
WorkingDirectory=/home/oxylabs/Scraper
ExecStart=/home/oxylabs/Scraper/venv/bin/python3 scrape.py

Restart=always
RestartSec=120

[Install]
WantedBy=multi-user.target

Here’s the basic rundown of the parameters used in the configuration file:

  • After – ensures you only start your Python script once the network is up. 

  • RestartSec – sleep time before restarting the service.

  • Restart – describes what to do if a service exits, is killed, or a timeout is reached. 

  • WorkingDirectory – current working directory of the script.

  • ExecStart – the command to execute.

Now, it’s time to tell systemd about the newly created daemon. Run the daemon-reload command:

Then, start your service:

systemctl start book-scraper

And finally, check whether your service is running:

$ systemctl status book-scraper
book-scraper.service - A script for scraping the book information
     Loaded: loaded (/etc/systemd/system/book-scraper.service; disabled; vendor preset: enabled)
     Active: active (running) since Thu 2022-09-08 15:01:27 EEST; 16min ago
   Main PID: 60803 (python3)
      Tasks: 1 (limit: 18637)
     Memory: 21.3M
     CGroup: /system.slice/book-scraper.service
             60803 /home/oxylabs/Scraper/venv/bin/python3 scrape.py

Sep 08 15:17:55 laptop python3[60803]: Scraping url https://books.toscrape.com/catalogue/shakespeares-sonnets_989/index.html
Sep 08 15:17:55 laptop python3[60803]: Scraping url https://books.toscrape.com/catalogue/sharp-objects_997/index.html
Sep 08 15:17:55 laptop python3[60803]: Scraping url https://books.toscrape.com/catalogue/sapiens-a-brief-history-of-humankind_996/index.html

Protip: use journalctl -S today -u book-scraper.service to monitor your logs in real-time.

Congrats! Now you can control your service via systemd.

Running a Python script as a Windows service

Running a Python script as a Windows service is not as straightforward as one might expect. Let’s start with the script changes.

To begin, change how the script is executed based on the number of arguments it receives from the command line.  

If the script receives a single argument, assume that Windows Service Manager is attempting to start it. It means that you have to run an initialization code. If zero arguments are passed, print some helpful information by using win32serviceutil.HandleCommandLine:

if __name__ == '__main__':
    if len(sys.argv) == 1:
        servicemanager.Initialize()
        servicemanager.PrepareToHostSingle(BookScraperService)
        servicemanager.StartServiceCtrlDispatcher()
    else:
        win32serviceutil.HandleCommandLine(BookScraperService)

Next, extend the special utility class and set some properties. The service name, display name, and description will all be visible in the Windows services utility (services.msc) once your service is up and running.

class BookScraperService(win32serviceutil.ServiceFramework):
    _svc_name_ = 'BookScraperService'
    _svc_display_name_ = 'BookScraperService'
    _svc_description_ = 'Constantly updates the info about books'

Finally, implement the SvcDoRun and SvcStop methods to start and stop the service. Here’s the script so far:

import sys
import servicemanager
import win32event
import win32service
import win32serviceutil
import json
import re
from pathlib import Path

import requests
from bs4 import BeautifulSoup


class BookScraperService(win32serviceutil.ServiceFramework):
    _svc_name_ = 'BookScraperService'
    _svc_display_name_ = 'BookScraperService'
    _svc_description_ = 'Constantly updates the info about books'

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.event = win32event.CreateEvent(None, 0, 0, None)

    def GetAcceptedControls(self):
        result = win32serviceutil.ServiceFramework.GetAcceptedControls(self)
        result |= win32service.SERVICE_ACCEPT_PRESHUTDOWN
        return result

    def SvcDoRun(self):
        urls = [
'https://books.toscrape.com/catalogue/sapiens-a-brief-history-of-humankind_996/index.html',
'https://books.toscrape.com/catalogue/shakespeares-sonnets_989/index.html',
'https://books.toscrape.com/catalogue/sharp-objects_997/index.html',
        ]

        index = 0

        while True:
            result = win32event.WaitForSingleObject(self.event, 5000)
            if result == win32event.WAIT_OBJECT_0:
                break

            url = urls[index % len(urls)]
            index += 1

            print('Scraping url', url)
            response = requests.get(url)

            soup = BeautifulSoup(response.content, 'html.parser')
            book_name = soup.select_one('.product_main').h1.text
            rows = soup.select('.table.table-striped tr')
            product_info = {row.th.text: row.td.text for row in rows}

            data_folder = Path('C:\\Users\\User\\Scraper\\dist\\scrape\\data')
            data_folder.mkdir(parents=True, exist_ok=True)

            json_file_name = re.sub('[\': ]', '-', book_name)
            json_file_path = data_folder / f'{json_file_name}.json'
            with open(json_file_path, 'w') as book_file:
                json.dump(product_info, book_file)

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.event)


if __name__ == '__main__':
    if len(sys.argv) == 1:
        servicemanager.Initialize()
        servicemanager.PrepareToHostSingle(BookScraperService)
        servicemanager.StartServiceCtrlDispatcher()
    else:
        win32serviceutil.HandleCommandLine(BookScraperService)

Now that you have the script, open a Windows terminal of your preference. If you’re new to using your computer’s command-line interface, you can learn the basics by following our guide about how to run a Python script in terminal.

Protip: if you’re using Powershell, make sure to include a .exe extension when running binaries to avoid unexpected errors.

Terminal

Terminal

Once the terminal is open, change the directory to the location of your script with a virtual environment, for example:

Next, install the experimental Python Windows extensions module, pypiwin32. You’ll also need to run the post-install script:

.\venv\Scripts\pip install pypiwin32
.\venv\Scripts\pywin32_postinstall.py -install

Unfortunately, if you attempt to install your Python script as a Windows service with the current setup, you’ll get the following error:

**** WARNING ****
The executable at "C:\Users\User\Scraper\venv\lib\site-packages\win32\PythonService.exe" is being used as a service.

This executable doesn't have pythonXX.dll and/or pywintypesXX.dll in the same
directory, and they can't be found in the System directory. This is likely to
fail when used in the context of a service.

The exact environment needed will depend on which user runs the service and
where Python is installed. If the service fails to run, this will be why.

NOTE: You should consider copying this executable to the directory where these
DLLs live - "C:\Users\User\Scraper\venv\lib\site-packages\win32" might be a good place.

However, if you follow the instructions of the error output, you’ll be met with a new issue when trying to launch your script:

Error starting service: The service did not respond to the start or control request in a timely fashion.

To solve this issue, you can add the Python libraries and interpreter to the Windows path. Alternatively, bundle your script and all its dependencies into an executable by using pyinstaller:

venv\Scripts\pyinstaller --hiddenimport win32timezone -F scrape.py

The —hiddenimport win32timezone option is critical as the win32timezone module is not explicitly imported but is still needed for the script to run.

Finally, let’s install the script as a service and run it by invoking the executable you’ve built previously:

PS C:\Users\User\Scraper> .\dist\scrape.exe install
Installing service BookScraper
Changing service configuration
Service updated

PS C:\Users\User\Scraper> .\dist\scrape.exe start
Starting service BookScraper
PS C:\Users\User\Scraper>

And that’s it. Now, you can open the Windows services utility and see your new service running.

Protip: you can read more about specific Windows API functions here.

The newly created service is running

The newly created service is running

Making your life easier by using NSSM on Windows

As evident, you can use win32serviceutil to develop a Windows service. But the process is definitely not that simple – you could even say it sucks! Well, this is where the NSSM (Non-Sucking Service Manager) comes into play.

Let’s simplify the script by only keeping the code that performs web scraping:

import json
import re
from pathlib import Path

import requests
from bs4 import BeautifulSoup

urls = ['https://books.toscrape.com/catalogue/sapiens-a-brief-history-of-humankind_996/index.html',
        'https://books.toscrape.com/catalogue/shakespeares-sonnets_989/index.html',
        'https://books.toscrape.com/catalogue/sharp-objects_997/index.html', ]

index = 0

while True:
    url = urls[index % len(urls)]
    index += 1

    print('Scraping url', url)
    response = requests.get(url)

    soup = BeautifulSoup(response.content, 'html.parser')
    book_name = soup.select_one('.product_main').h1.text
    rows = soup.select('.table.table-striped tr')
    product_info = {row.th.text: row.td.text for row in rows}

    data_folder = Path('C:\\Users\\User\\Scraper\\data')
    data_folder.mkdir(parents=True, exist_ok=True)

    json_file_name = re.sub('[\': ]', '-', book_name)
    json_file_path = data_folder / f'{json_file_name}.json'
    with open(json_file_path, 'w') as book_file:
        json.dump(product_info, book_file)

Next, build a binary using pyinstaller:

venv\Scripts\pyinstaller -F simple_scrape.py

Now that you have a binary, it’s time to install NSSM by visiting the official website. Extract it to a folder of your choice and add the folder to your PATH environment variable for convenience.

NSSM in a folder

NSSM in a folder

Then, run the terminal as an admin.

Running as an admin

Running as an admin

Once the terminal is open, change the directory to your script location:

Finally, install the script using NSSM and start the service:

nssm.exe install SimpleScrape C:\Users\User\Scraper\dist\simple_scrape.exe
nssm.exe start SimpleScrape

Protip: if you have issues, redirect the standard error output of your service to a file to see what went wrong:

nssm set SimpleScrape AppStderr C:\Users\User\Scraper\service-error.log

NSSM ensures that a service is running in the background, and if it doesn’t, you at least get to know why.

Conclusion

Regardless of the operating system, you have various options for setting up Python scripts for recurring web scraping tasks. Whether you need the configurability of systemd, the flexibility of Windows services, or the simplicity of NSSM, be sure to follow this tried & true guide as you navigate their features.

If you are interested in more Python automation solutions for web scraping applications or web scraping with Python, take a look at our blog for various tutorials on all things web scraping. We also offer an advanced solution, Web Scraper API, designed to collect public data from most websites automatically and hassle-free. In addition, you can use a Scheduler feature to schedule multiple web scraping jobs at any frequency you like.

People also ask

What is systemd?

Systemd is a powerful tool for managing processes. It also provides logging and dependency management, for example, starting processes only when a network is available or once a previous service has been started.

What is the difference between systemd and systemctl?

Systemctl is a utility and is part of systemd. Among other things, it allows you to manage services and check their status.

Can I use cron instead of systemd?

You definitely can if it suits your needs. However, if you need more control over the service, systemd is the way to go. It allows you to start services based on certain conditions and is perfect for dealing with long-running scripts. It even allows you to run scripts in a similar way to crontab by using timers.

What’s the difference between a daemon and a service?

The word daemon comes from MIT’s Project MAC, which first coined the term in 1963. It is, by definition, an agent that works tirelessly in the background. Later Windows and Linux adopted the term as an alternative name. Therefore, this article uses the words daemon and service interchangeably.

About the author

author avatar

Augustas Pelakauskas

Senior Technical Copywriter

Augustas Pelakauskas was a Senior Technical Copywriter at Oxylabs. Coming from an artistic background, he is deeply invested in various creative ventures — the most recent being writing. After testing his abilities in freelance journalism, he transitioned to tech content creation. When at ease, he enjoys the sunny outdoors and active recreation. As it turns out, his bicycle is his fourth-best friend.

All information on Oxylabs Blog is provided on an «as is» basis and for informational purposes only. We make no representation and disclaim all liability with respect to your use of any information contained on Oxylabs Blog or any third-party websites that may be linked therein. Before engaging in scraping activities of any kind you should consult your legal advisors and carefully read the particular website’s terms of service or receive a scraping license.

Related articles

ISO/IEC 27001:2017 certified products:

Scale up your business with Oxylabs®

Forget about complex web scraping processes

Choose Oxylabs’ advanced web intelligence collection solutions to gather real-time public data hassle-free.

teaser

Hi guys, today’s post is just for the ones of you that work with the “OS of the misoriented slashes”: Microsoft Windows. :)

Have you ever had the need of writing a Python script that could run in background as a Windows Service? In this post, you will learn how to do it in less than 10 minutes, no jokes.

I will skip all the introduction about Windows Services, how convenient they could be, how much could be appreciated the fact that they can be run in background even when the user is logged off etc… I mean, if you can code in Python and you use Windows I bet you already know what a Windows Service is, don’t you?

So, first of all, let’s start by installing the Python for Windows extensions:

c:test> pip install pywin32

Once you have done it, let’s write this base class, your Windows service will be a subclass of this base class.

'''
SMWinservice
by Davide Mastromatteo

Base class to create winservice in Python
-----------------------------------------

Instructions:

1. Just create a new class that inherits from this base class
2. Define into the new class the variables
   _svc_name_ = "nameOfWinservice"
   _svc_display_name_ = "name of the Winservice that will be displayed in scm"
   _svc_description_ = "description of the Winservice that will be displayed in scm"
3. Override the three main methods:
    def start(self) : if you need to do something at the service initialization.
                      A good idea is to put here the inizialization of the running condition
    def stop(self)  : if you need to do something just before the service is stopped.
                      A good idea is to put here the invalidation of the running condition
    def main(self)  : your actual run loop. Just create a loop based on your running condition
4. Define the entry point of your module calling the method "parse_command_line" of the new class
5. Enjoy
'''

import socket

import win32serviceutil

import servicemanager
import win32event
import win32service


class SMWinservice(win32serviceutil.ServiceFramework):
    '''Base class to create winservice in Python'''

    _svc_name_ = 'pythonService'
    _svc_display_name_ = 'Python Service'
    _svc_description_ = 'Python Service Description'

    @classmethod
    def parse_command_line(cls):
        '''
        ClassMethod to parse the command line
        '''
        win32serviceutil.HandleCommandLine(cls)

    def __init__(self, args):
        '''
        Constructor of the winservice
        '''
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        socket.setdefaulttimeout(60)

    def SvcStop(self):
        '''
        Called when the service is asked to stop
        '''
        self.stop()
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)

    def SvcDoRun(self):
        '''
        Called when the service is asked to start
        '''
        self.start()
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_, ''))
        self.main()

    def start(self):
        '''
        Override to add logic before the start
        eg. running condition
        '''
        pass

    def stop(self):
        '''
        Override to add logic before the stop
        eg. invalidating running condition
        '''
        pass

    def main(self):
        '''
        Main class to be ovverridden to add logic
        '''
        pass

# entry point of the module: copy and paste into the new module
# ensuring you are calling the "parse_command_line" of the new created class
if __name__ == '__main__':
    SMWinservice.parse_command_line()

Let’s examine the class we have just introduced a little.

def SvcDoRun(self): it’s the method that will be called when the service is requested to start.

def SvcStop(self): it’s the method that will be called when the service is requested to stop.

def start(self): it’s a method that you will be asked to override if you need to do something when the service is starting (before started)

def stop(self): it’s the method that you will be asked to override if you need to do something when the service is stopping (before stopped)

def main(self): it’s the method that will contain the logic of your script, usually in a loop that keeps it alive until the service is stopped.

def parse_command_line(cls): it’s the method that handles the command line interface that you can use to install and update your windows service

Can you see how easy it is with pywin32 to interface with the system to create a Windows Service? The last mention is for the following variables:

svc_name = "PythonCornerExample"
svc_display_name = "Python Corner's Winservice Example"
svc_description = "That's a great winservice! :)"

These are just three variables that contain the name of the service, the “friendly name” that will be used by Windows to display the name on the mmc console and a short description of your service.

As always, enough talk, let’s code something useful!


Let’s pretend that we want to create a Winservice that, when started, creates a random file on our C: drive every 5 seconds.

What? Do you think it is stupid?
Well, install it on your boss PC, set the destination folder as its user’s desktop and you will change your mind. :)

However, how can you achieve this result? Super easy.

  • Subclass the SMWinservice class we have just met.
  • On the new class, override the three variables _svc_name_, _svc_display_name_ and _svc_description_.
  • Override the “start” method to set the running condition. Setting a boolean variable will be enough for that.
  • Override the “stop” method to invalidate the running condition when the service is requested to be stopped.
  • Override the “main” method to add the logic of creating a random file every 5 seconds
  • Add the call at the “parse_command_line” function to handle the command line interface.

The result should be something like this:

import time
import random
from pathlib import Path
from SMWinservice import SMWinservice

class PythonCornerExample(SMWinservice):
    _svc_name_ = "PythonCornerExample"
    _svc_display_name_ = "Python Corner's Winservice Example"
    _svc_description_ = "That's a great winservice! :)"

    def start(self):
        self.isrunning = True

    def stop(self):
        self.isrunning = False

    def main(self):
        i = 0
        while self.isrunning:
            random.seed()
            x = random.randint(1, 1000000)
            Path(f'c:{x}.txt').touch()
            time.sleep(5)

if __name__ == '__main__':
    PythonCornerExample.parse_command_line()

That’s it! Now it’s time to install our newly created winservice. Just open a command prompt, navigate to your script directory and install the service with the command:

C:test> python PythonCornerExample.py install
Installing service PythonCornerExample
Service installed

In the future, if you want to change the code of your service, just modify it and reinstall the service with

C:test> python PythonCornerExample.py update
Changing service configuration
Service updated

Now, open the “Services” msc snap in

locate your new PythonCornerExample winservice, and right click and choose properties. Here you can start your service and configure it at your will.

Now try to start your service and go to see your C: folder contents.

Can you see all these files being created to your C: folder? Yeah, that’s working!

But now it’s time to stop it!  :) You can do it from the previous windows or just by using the command line

C:test> net stop PythonCornerExample

Il servizio Python Corner's Winservice Example sta per essere arrestato.. 
Servizio Python Corner's Winservice Example arrestato.

If something goes wrong…

There are a couple of known problems that can happen writing Windows Services in Python. If you have successfully installed the service but starting it you get an error, follow this iter to troubleshoot your service:

  • Check if Python is in your PATH variable. It MUST be there. To check this, just open a command prompt and try starting the python interpreter by typing “python”. If it starts, you are ok.
  • Be sure to have the file C:\Program Files\Python36\Lib\site-packages\win32\pywintypes36.dll (please note that “36” is the version of your Python installation). If you don’t have this file, take it from C:\Program Files\Python36\Lib\site-packages\pywin32_system32\pywintypes36.dll and copy it into C:\Program Files\Python36\Lib\site-packages\win32

If you still have problems, try executing your Python script in debug mode. To try this with our previous example, open a terminal, navigate to the directory where the script resides and type

c:test> python PythonCornerExample.py debug

Ok, that’s all for today, this was just a brief introduction to developing Windows Services with Python. Try it by yourself and … happy coding!

D.

Introduction

If you want to run a Python script as a Windows service you can use the Non-Sucking Service Manager to create the service.
This application allows you to easily create a service using any executable or batch script that gets
treated as a proper Windows service that you can manage Windows services by running services.msc or by going to the Services tab from the Task Manager.

The most common use case for running a Python script as a service is to ensure an application is always run
and starts running when you log in.
For example, if you have a web application that you want to stay running whenever the computer is up.
I have used this method to run Flask applications and other utilities.

Setup

Download nssm and extract nssm.exe.
NSSM is a single file nssm.exe that does not need any special installation.

For convenience, you may want to place the file inside a directory in your %PATH%
environment variable, otherwise you will need to execute it using the full path.
To learn how to set environment variables in Windows, check out my tutorial
Set Environment Variables in Windows.

You will also need Python installed.

I recommend creating a virtual environment. I usually create at least one virtual environment in
my user’s home directory in a directory named venv. Then I can be sure Python is available in C:\Users\<my_user>\venv\Scripts\python.exe.
To learn how to setup a Python virtual environment, check out my tutorial
Python Virtual Environments Tutorial.

IMPORTANT: When running nssm commands, tou need to run the Command Prompt as an Adminstrator. Right click on Command Prompt and choose Run as Administrator.

Create Windows service to run Python script

To create a custom service, you simply need to run nssm install and tell it the name of your new service
and what program you want to run. In this case we are calling Python from the virtual environment
and running a Python script from my user’s home directory.

nssm.exe install "MyCustomService" "C:\Users\nanodano\venv\Scripts\python.exe" "C:\Users\nanodano\myscript.py"

You should see a message that says something like:

Service "MyCustomService" installed successfully!

It will default to have Startup type: Automatic. This means it will start automatically when the computer restarts.

Start and stop your custom service

You can use the normal Services manager services.msc or you can use NSSM from the Command Prompt.
You can start and stop the service like this:

nssm.exe start MyCustomService
nssm.exe stop MyCustomService

Delete the service

If you no longer want the service you can remove it with the following command:

nssm.exe remove "MyCustomService"

Conclusion

After reading this, you should understand how to create your own custom Windows service to run a Python script using NSSM.
You should understand how to create the service and remove it as well as how to start, stop, and restart it.
You should understand how to run a specific Python interpreter to run a Python script.

References

  • Non-Sucking Service Manager
  • Python
  • Set Environment Variables in Windows
  • Python Virtual Environments Tutorial

Running a Python Script as a Service in Windows 🐍🚀

So, you’ve got a Python script that you want to run as a service in Windows. Maybe it’s part of a larger system with interrelated objects stored in a database, and you want to provide a higher level interface for operations on those objects. Whatever the case may be, you’re in the right place! In this blog post, we’ll explore how to run a Python script as a service in Windows, address common issues, and provide easy solutions. Let’s dive in! 💥

Understanding the Challenge 🤔

Running a Python script as a service on Windows can be a bit tricky if you’re not familiar with Windows services. Services are programs that run in the background without user interaction, automatically starting when the system boots up. In order to achieve this, we need to perform a few steps, which we’ll cover in detail in the following sections.

Step 1: Convert the Python script to an executable 📦

Windows services require an executable file to run, so we need to convert our Python script into an executable format. There are several tools available for this task, such as PyInstaller or py2exe. These tools package your Python script into a standalone executable file that can be executed as a service.

Here’s an example using PyInstaller:

pyinstaller --onefile your_script.py

This command will create a single executable file (your_script.exe) in the dist directory. This is the file we’ll use to run our Python script as a service.

Step 2: Install the Service 🛠️

To install the service, we’ll be using the pywin32 library. If you don’t have it installed, you can install it using pip:

pip install pywin32

Once you have pywin32 installed, you can use the pywin32 API to install and manage the service. Here’s an example of how to install the service using the pywin32 library:

import win32serviceutil
import servicemanager
import win32event
import win32service

class MyService(win32serviceutil.ServiceFramework):
    _svc_name_ = 'MyService'
    _svc_display_name_ = 'My Service'

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)

    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):
        # Add your Python script logic here
        pass

if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(MyService)

In the example above, you’ll need to replace MyService with the desired name of your service, and My Service with the display name you want to appear in the services list.

Step 3: Start and Manage the Service 🚀

Once you have your service installed, you can start and manage it using the native Windows utilities. You can open the Services Manager by typing «services.msc» in the Windows Run dialog (press Win + R to open the Run dialog).

In the Services Manager, locate your service by its name (e.g., «MyService»). You can start, stop, and restart the service using the provided controls. You can also configure the service to start automatically on system boot, or you can start it manually.

Conclusion and Call-to-Action 📢

Running a Python script as a service in Windows is indeed possible, and with the help of tools like PyInstaller and the pywin32 library, it becomes a straightforward process. By following the steps outlined in this blog post, you can convert your Python script to an executable, install it as a service, and manage it using the native Windows utilities.

Now that you have a better understanding of how to run a Python script as a service in Windows, it’s time to put your newfound knowledge into action! Give it a try with one of your own Python scripts and see how it works for you. And don’t forget to share your experiences and thoughts in the comments below! 💬👇

Happy scripting! 🐍💻

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Как вернуть microsoft office на windows 10
  • Эмулятор контроллера для pc windows 10
  • Отключить hyper v windows 10 cmd
  • Сбросить dhcp кэш windows
  • Windows 10 как настроить встроенный антивирус