A Python package for building Windows services.
Project description
windowsservice
windowsservice
is a Python package for building Windows services.
The key features are:
- Easy to use
- Support for PyInstaller
- Support for
multiprocessing
Getting ready
Create and activate a virtual environment:
python -m venv venv
.\venv\Scripts\activate
Installation
Install the windowsservice package from PyPI:
pip install windowsservice
The windowsservice package depends on pywin32 created by Mark Hammond. Installing the windowsservice package also installs the pywin32 dependency.
Coding
-
Import the
BaseService
class:from windowsservice import BaseService
-
Create a new subclass that inherits from the
BaseService
class. -
Define the following three class variables in the subclass:
_svc_name_
: A unique identifier for your service._svc_display_name_
: The name shown in the service control manager._svc_description_
: The description shown in the service control manager.
For example:
_svc_name_ = "MyWindowsService" _svc_display_name_ = "My Windows Service" _svc_description_ = "This is my custom Windows service."
-
Override the following methods in the subclass:
-
start(self)
: This method is invoked when the service starts. Override this to add setup code, such as initializing a running condition. -
main(self)
: This method is invoked afterstart
. Override this to create a run loop, typically based on a running condition. -
stop(self)
: This method is invoked when the service stops. Override this to add cleanup code, such as releasing resources or to invalidate a running condition.
For example:
def start(self): self.is_running = True def main(self): while self.is_running: time.sleep(5) def stop(self): self.is_running = False
-
-
Call the
parse_command_line
class method from the module's entry point. This handles command-line arguments for installing, starting, stopping, and debugging the service.For example:
if __name__ == "__main__": ExampleService.parse_command_line()
Examples
Basic example (example_service.py):
import time
from windowsservice import BaseService, utils
class ExampleService(BaseService):
"""Example Windows service in Python."""
_svc_name_ = "PythonExampleWindowsService"
_svc_display_name_ = "Python Example Windows Service"
_svc_description_ = "Example Windows service in Python"
def start(self):
self.is_running = True
def main(self):
while self.is_running:
utils.log(f"{self._svc_display_name_} is running...")
time.sleep(5)
def stop(self):
self.is_running = False
if __name__ == "__main__":
ExampleService.parse_command_line()
Example that demonstrates support for multiprocessing
(example_service_multiprocessing.py):
import time
from multiprocessing import Process, freeze_support
from windowsservice import BaseService, utils
def stub_server():
"""
A function that simulates a server process hosted by the Windows service.
This function logs a message every 5 seconds for a total of 100 times.
"""
for _ in range(100):
utils.log("Hello from a process hosted by a Windows service...")
time.sleep(5)
class ExampleService(BaseService):
"""Example Windows service in Python."""
_svc_name_ = "PythonExampleWindowsService"
_svc_display_name_ = "Python Example Windows Service"
_svc_description_ = "Example Windows service in Python"
def start(self):
self.server_process = Process(target=stub_server)
def main(self):
self.server_process.start()
self.server_process.join()
def stop(self):
if self.server_process:
self.server_process.terminate()
if __name__ == "__main__":
freeze_support()
ExampleService.parse_command_line()
Usage
Some interactions with a Windows service may require administrative privileges, so you must use an elevated command line interface.
All arguments and options can be listed by invoking the module:
python .\examples\example_service.py
Usage: 'example_service.py [options] install|update|remove|start [...]|stop|restart [...]|debug [...]'
Options for 'install' and 'update' commands only:
--username domain\username : The Username the service is to run under
--password password : The password for the username
--startup [manual|auto|disabled|delayed] : How the service starts, default = manual
--interactive : Allow the service to interact with the desktop.
--perfmonini file: .ini file to use for registering performance monitor data
--perfmondll file: .dll file to use when querying the service for
performance data, default = perfmondata.dll
Options for 'start' and 'stop' commands only:
--wait seconds: Wait for the service to actually start or stop.
If you specify --wait with the 'stop' option, the service
and all dependent services will be stopped, each waiting
the specified period.
Install the service
If you want to install the service from the example_service.py
example, run:
python .\examples\example_service.py install
Installing service PythonExampleWindowsService
Service installed
You can also choose to install the service so that it will start automatically when Windows starts:
python .\examples\example_service.py --startup=auto install
Start the service
To start/stop the service you can now use the service control manager.
Or, from the command line interface, you can run:
python .\examples\example_service.py start
To start the service in debug mode, run:
python .\examples\example_service.py debug
To verify that the service is working, make sure it is running, and then look into the Windows Event Viewer or, if it is running in debug mode, look at the standard output stream. You should see a message every 5 seconds.
Remove the service
To remove the service, run:
python .\examples\example_service.py remove
PyInstaller
To bundle the service into a convenient standalone executable, you can use PyInstaller.
Install PyInstaller
Install PyInstaller inside your activated virtual environment:
pip install pyinstaller
Create executable
To create a standalone (one-file) executable, use the pyinstaller
command:
pyinstaller .\examples\example_service.py --clean --noupx --onefile --noconfirm --hidden-import=win32timezone
The resulting example_service.exe
executable can be found in the .\dist
directory.
You can use this executable with the same arguments and options as discussed above. For example, to install the service, run:
.\dist\example_service.exe install
You can also create a one-folder bundle. Because the executable does not have to be unpacked first in a temporary location, this has the advantage of making the service start faster.
pyinstaller .\examples\example_service.py --clean --noupx --onedir --noconfirm --hidden-import=win32timezone
In this case, the resulting executable can be found in the dist\example_service
directory.
Acknowledgement
This package utilizes the pywin32 library, a collection of Python extensions for Windows. The maintenance and development of this library is credited to Mark Hammond and others in the Python community. Their contributions enable the development of Windows services in Python. Please note that the windowsservice
package does not aim to replace pywin32
or win32serviceutil.ServiceFramework
, it's just here to make it a little bit easier to use.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file windowsservice-2.0.0.tar.gz
.
File metadata
- Download URL: windowsservice-2.0.0.tar.gz
- Upload date:
- Size: 8.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.12.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6a83d025f0afbc33740a172fefd1f4a833a6fe3287ec17f3a205f23dbc2fecc3 |
|
MD5 | fb061a64d79e584b322e630de11c5e6b |
|
BLAKE2b-256 | 608e3b4feda542c85e95e9e6d03e212336c64c75c7ced3000e14a16b1225954a |
File details
Details for the file windowsservice-2.0.0-py3-none-any.whl
.
File metadata
- Download URL: windowsservice-2.0.0-py3-none-any.whl
- Upload date:
- Size: 7.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.12.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | be812a4c0f19fa508175f51964ee8f56bcc27059a6a7ccffac75de55d2848012 |
|
MD5 | 7de819e53fc5d5ffb13da4263cbc38d6 |
|
BLAKE2b-256 | 627c3a01ef7b0e13f593fd42877c7e1f4f039a6d7dcb525a41929b1fbd514381 |