Python 3 executable as windows service
Solution 1
tldr Python 3.5 Windows Service build with pyinstaller : gist
Here a simple Windows Service with python :
WindowsService.py
import servicemanager
import socket
import sys
import win32event
import win32service
import win32serviceutil
class TestService(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):
rc = None
while rc != win32event.WAIT_OBJECT_0:
with open('C:\\TestService.log', 'a') as f:
f.write('test service running...\n')
rc = win32event.WaitForSingleObject(self.hWaitStop, 5000)
if __name__ == '__main__':
if len(sys.argv) == 1:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(TestService)
servicemanager.StartServiceCtrlDispatcher()
else:
win32serviceutil.HandleCommandLine(TestService)
Create an exe with pyinstaller (pip install pyinstaller
) and python 3.5 :
(env)$ python -V
Python 3.5.2
(env)$ pip freeze
PyInstaller==3.2
(env)$ pyinstaller -F --hidden-import=win32timezone WindowsService.py
Install and run the service
(env) dist\WindowsService.exe install
Installing service TestService
Service installed
(env) dist\WindowsService.exe start
Starting service TestService
Check C:\\TestService.log
file.
Stop and clean
(env) dist\WindowsService.exe stop
(env) dist\WindowsService.exe remove
Solution 2
I've edited the Win32Service.c
in the cx_freeze
src for python3
support
Edited it with some preprocessor commands, for python2 support too (but not tested for python2 yet)
- download sources of
cx_freeze
from pypi and extract it - download cx_logging and extract it to the
cx_freeze-4.3.4
directory - replace the
Win32Service.c
file incx_Freeze-4.3.4\source\bases
with my edited version - edit line 170 in
setup.py
fromif moduleInfo is not None and sys.version_info[:2] < (3, 0):
toif moduleInfo is not None:
- run
python setup.py build
incx_freeze-4.3.4
directory (you must have MSC installed to compile the C source files) - copy
cx_Freeze-4.3.4\build\lib.win32-3.4\cx_Freeze\bases\Win32Service.exe
toC:\Python34\Lib\site-packages\cx_Freeze\bases
(or the path where your python3 is installed) - now you can create frozen exe with the
Win32Service
base (no more thecx_Freeze.freezer.ConfigError: no base named Win32Service
error)
Solution 3
It appears Win32Service was updated with Python 3.x support within the cx_Freeze project as a result of this thread. This user originally had the same issue you reported, so I'm assuming this will also resolve your issue.
Based on the error reported, it's caused when _GetBaseFileName() within Freezer.py fails to find the compiled Win32Service.exe. This executable should be built when cx_Freeze gets built/installed.
If it's not too much to ask, can search the installed cx_Freeze installation directory for "Win32Service.exe" and confirm that it exists. Hopefully this gets you one step closer.
Related videos on Youtube
AmitE
Updated on June 04, 2022Comments
-
AmitE almost 2 years
I'm trying to write a windows Service in python, but the tricky part is i want to deploy it on a machine that doesn't have python. I've successfully created a service like this, and it works if i run from my machine. the problem starts when i try to convert it to an exe and then try to install it. first i tried to use cx_freeze service example, (seen here), the setup.py look like this :
from cx_Freeze import setup, Executable options = {'build_exe': {'includes': ['ServiceHandler']}} executables = [Executable('Config.py', base='Win32Service', targetName='gsr.exe')] setup(name='GSR', version='0.1', description='GSR SERVICE', executables=executables, options=options )
and config.py is:
NAME = 'GSR_%s' DISPLAY_NAME = 'GSR TEST - %s' MODULE_NAME = 'ServiceHandler' CLASS_NAME = 'Handler' DESCRIPTION = 'Sample service description' AUTO_START = True SESSION_CHANGES = False
but when i try to build it (python setup.py build) i get an error: "cx_Freeze.freezer.ConfigError: no base named Win32Service"
Second, i tried using a regular cx_freeze setup, the exe i get installs the service fine but once i try to start it i get an error: "Error 1053: The service did not respond to the start or control request in a timely fashion"
setup.py - python 3.3 regualr exe, installs the service but when trying to start it sends an error:
from cx_Freeze import setup, Executable packages = ['win32serviceutil','win32service','win32event','servicemanager','socket','win32timezone','cx_Logging','ServiceHandler'] build_exe_options = {"packages": packages} executable = [Executable("ServiceHandler.py")] setup( name = "GSR_test", version = "1.0", description = "GSR test service", options = {"build_exe": build_exe_options}, executables = executable)
finally, I managed to get it to work in python 2.7 using py2exe, but py2exe isn't available for python 3.3 and I my code is in 3.3
i guess the problem is in the configuration of the setup.py im using with cx_freeze. any ideas ??
my ServiceHandler:
import pythoncom import win32serviceutil import win32service import win32event import servicemanager import socket from test import test import threading class AppServerSvc (win32serviceutil.ServiceFramework): _svc_name_ = "GSR_test" _svc_display_name_ = "GSR test Service" def __init__(self,args): win32serviceutil.ServiceFramework.__init__(self,args) self.hWaitStop = win32event.CreateEvent(None,0,0,None) socket.setdefaulttimeout(60) self.app = test() self.flag = threading.Event() def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) win32event.SetEvent(self.hWaitStop) self.flag.set() def SvcDoRun(self): servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED, (self._svc_name_,'')) self.main() def main(self): t = threading.Thread(target=self.app.run) t.start() self.flag.wait() raise SystemExit if __name__ == '__main__': win32serviceutil.HandleCommandLine(AppServerSvc)
Setup.py , python 2.7 using py2exe that works: (taken from here)
from distutils.core import setup import py2exe setup( service = ["ServiceHandler"], description = "SERVICE TEST", modules = ["GSR_test"], cmdline_style='pywin32', )
Thanks, Amit
-
Thomas K about 10 yearsThe Win32service base only supports Python 2 at the moment. It's waiting for someone to add Python 3 support.
-
-
AmitE over 8 yearsWhile the base file seems to be updated if i try to freeze a service (using the provided example from cx_freeze) i'm still getting an error - cx_Freeze.freezer.ConfigError: no base named Win32Service. and indeed if I go and look at the bases folder (with the exe not the c file) it's still missing (no win32Service.exe).. maybe it just need to be compiled and someone fortgot. Using cx_freeze v4.3.4
-
ZachM over 6 yearsFYI a regular pip install of cx_Freeze won't have the cx_Logging folder in the folder above it, so the Win32Service base will not be compiled. If you download the source to both (to /tmp/cx_Freeze/ and /tmp/cx_Logging) then run
python setup.py install
on cx_Logging THEN cx_Freeze, you'll end up with the Win32Service base. -
tulsluper over 6 yearsIt really works! Thank you! (Python 3.6.3, PyInstaller==3.3)
-
shasan almost 5 yearsHow is
TestService
linked to the main application script?