I've implemented a windows service, this service has no problem before compiling with pyinstaller but after that on service start command it gives 1053 error.
Windows service code:
import sys
import win32service
import win32event
import socket
import win32api
import win32serviceutil
class AppServerSvc(win32serviceutil.ServiceFramework):
_svc_name_ = "test"
_svc_display_name_ = "test"
_stoped = False
def __init__(self, *args):
win32serviceutil.ServiceFramework.__init__(self, *args)
self.stop_event = win32event.CreateEvent(None, 0, 0, None)
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
self._stoped = True
def SvcDoRun(self):
self.ReportServiceStatus(win32service.SERVICE_RUNNING)
self.main()
def main(self):
while True:
if self._stoped:
break
pass
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(AppServerSvc)
Finally i solved this problem, there was a broken link to one of references in windows service. This is the right config for py2exe which solved my problem:
opts = {'py2exe': {
'dll_excludes': ['libzmq.pyd', 'OLEAUT32.dll', 'USER32.dll', 'SHELL32.dll', 'ole32.dll',
'MSVCP90.dll', 'ADVAPI32.dll', 'NETAPI32.dll', 'WS2_32.dll', 'GDI32.dll',
'VERSION.dll', 'KERNEL32.dll', 'WINSPOOL.DRV', 'mfc90.dll', 'ntdll.dll'],
'includes': ['UserList', 'UserString', 'commands', 'zmq.backend.cython'],
'dist_dir': "dist"
}}
setup(service=[service], options=opts, zipfile=None,data_files=[(os.path.join(os.getcwd(), 'dist'), (zmq.libzmq.__file__,))])
To use my win32serviceutil.ServiceFramework class in an exe pyInstaller produced, I needed to add a few .pyd files to the directory containing the exe e.g. win32service.pyd and win32event.pyd. Assuming you've used the standard install paths for your libraries, these files are found here:
C:\Python27\Lib\site-packages\win32
Related
I have a Django app that I'm trying to run via Cherrypy on Windows Server. I have below code in the service creation script.
import os
import sys
service_directory = os.path.dirname(__file__)
source_directory = os.path.abspath(service_directory)
os.chdir(source_directory)
venv_base = os.path.abspath(os.path.join(source_directory, ".venv"))
print(venv_base)
sys.path.append(".")
old_os_path = os.environ['PATH']
os.environ['PATH'] = os.path.join(venv_base, "Scripts")+ os.pathsep + old_os_path
site_packages = os.path.join(venv_base, "Lib", "site-packages")
prev_sys_path = list(sys.path)
import site
site.addsitedir(site_packages)
sys.real_prefix = sys.prefix
sys.prefix = venv_base
new_sys_path = list()
for item in list(sys.path):
if item not in prev_sys_path:
new_sys_path.append(item)
sys.path.remove(item)
sys.path[:0] = new_sys_path
import pathlib
import subprocess
import traceback
import servicemanager
import win32event
import win32service
import win32serviceutil
from win32api import SetConsoleCtrlHandler
class AppServerSvc(win32serviceutil.ServiceFramework):
"""
Service Create class
"""
_svc_name_ = "MyService" # service name
_svc_display_name_ = "MyService" # display name
def __init__(self, args):
"""
Constructor
"""
win32serviceutil.ServiceFramework.__init__(self, args)
SetConsoleCtrlHandler(lambda x: True, True)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
def SvcStop(self):
"""
Function to stop the windows service
"""
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
self.proc.terminate()
def SvcDoRun(self):
"""
Function to create and start the windows service
"""
self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
try:
self.main()
except Exception as exp_msg:
servicemanager.LogErrorMsg(traceback.format_exc())
os._exit(-1)
def main(self):
"""
Script to run as the windows service
"""
#env_file.load(f'{os.path.join(pathlib.Path(__file__).parent.absolute(), "config.env")}')
#settings.set_env_variables()
self.ReportServiceStatus(win32service.SERVICE_RUNNING)
self.proc = subprocess.Popen(f"python"
f" {os.path.join(pathlib.Path(__file__).parent.absolute(), 'cherryd.py')} 1"
, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
stdin=subprocess.DEVNULL)
stdout, stderr = self.proc.communicate()
print(stdout)
if (self.proc.poll() == 0):
servicemanager.LogMsg(f"Successfully started the process with PID: {self.proc.pid}")
else:
servicemanager.LogErrorMsg(f"Failed to start the services")
if __name__ == '__main__':
# Start of the process
win32serviceutil.HandleCommandLine(AppServerSvc)
I'm able to install this service using python service.py install, no issues here.
When I start the service python service.py start I get error Error starting service: The service did not respond to the start or control request in a timely fashion.
When I do python service.py debug, everything works normal and I'm able to access the app using FQDN. Why does the service not work when started normally and work only during debug mode.
Have read multiple posts on similar errors but nothing helped. I'm using Python 3.8 and have added the venv Scripts directory to PATH as well. Can someone please help.
Update
Started the service with my user account and it worked, still don't understand how it worked in debug mode.
I wrote a simple python http server to serve the files(folders) of the present working directory.
import socketserver
http=''
def httpServer(hostIpAddress):
global http
socketserver.TCPServer.allow_reuse_address=True
try:
with socketserver.TCPServer((hostIpAddress,22818),SimpleHTTPRequestHandler) as http:
print(1123)
http.serve_forever()
except Exception as e:
print(str(e))
if __name__ == '__main__':
httpServer('192.168.1.2')
this code works as expected .It serves the contents.
However when i Freeze it (convert ist to executable) using cx-freeze . It does not serve the files .IN chrome it outs ERR_EMPTY_RESPONSE. I tried other browsers but to no avail.
My setup.py for the freeze is
executables = [
Executable("test_http.py", base=base,target_name="test_http",shortcutName="test_http",shortcutDir="DesktopFolder")
]
setup(
name="test_http",
options={"build_exe":build_exe_option,"bdist_msi":bdist_msi_options},
executables=executables
)
The .exe works without any error and you can even see the program running in task manager.
i used:
cx-freeze(i tried version 6.6,6.7,6.8)
python 3.7.7 32 bits
os : windpows 8.1
Thanks in advance.
Instead of using a function httpserver , I used class and it build the exe without any problem and now the http server runs even in its executable form.
Credit to: https://stackoverflow.com/users/642070/tdelaney for providing this solution at :
https://pastebin.com/KsTmVWRZ
import http.server
import threading
import functools
import time
# Example simple http server as thread
class SilentHandler(http.server.SimpleHTTPRequestHandler):
def log_message(self, format, *args, **kwargs):
# do any logging you like there
pass
class MyHttpServerThread(threading.Thread):
def __init__(self, address=("0.0.0.0",8000), target_dir="."):
super().__init__()
self.address = address
self.target_dir = "."
self.server = http.server.HTTPServer(address, functools.partial(SilentHandler, directory=self.target_dir))
self.start()
def run(self):
self.server.serve_forever(poll_interval=1)
def stop(self):
self.server.shutdown() # don't call from this thread
# test
if __name__ == "__main__":
http_server = MyHttpServerThread()
time.sleep(10)
http_server.stop()
print("done")
I need to run my python app as windows service.
I'm able to do that using commands,python fservice.py install
python fservice.py start
Now, i want to create exe for my app using py2exe.
I've followed code from this question: link
setup.py
from distutils.core import setup
import py2exe
import sys
if len(sys.argv) == 1:
sys.argv.append("py2exe")
sys.argv.append("-q")
class Target:
def __init__(self, **kw):
self.__dict__.update(kw)
# for the versioninfo resources
self.version = "0.0.1"
self.company_name = "flotomate"
self.copyright = "no copyright"
self.name = "flotomate"
myservice = Target(
# used for the versioninfo resource
description = "flotomate",
# what to build. For a service, the module name (not the
# filename) must be specified!
modules = ["fservice"]
)
setup(
service = [myservice]
)
fservice.py
import sys
import servicemanager
import win32serviceutil
import win32service
import win32event
import win32api
from pagent import app
class fservice(win32serviceutil.ServiceFramework):
_svc_name_ = 'flotomate' #here is now the name you would input as an arg for instart
_svc_display_name_ = 'flotomate' #arg for instart
_svc_description_ = 'flotomate'# arg from instart
def __init__(self, *args):
win32serviceutil.ServiceFramework.__init__(self, *args)
self.log('init')
self.stop_event = win32event.CreateEvent(None, 0, 0, None)
#logs into the system event log
def log(self, msg):
import servicemanager
servicemanager.LogInfoMsg(str(msg))
def sleep(self, minute):
win32api.Sleep((minute*1000), True)
def SvcDoRun(self):
self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
try:
self.ReportServiceStatus(win32service.SERVICE_RUNNING)
self.log('start')
self.start()
self.log('wait')
win32event.WaitForSingleObject(self.stop_event, win32event.INFINITE)
self.log('done')
except Exception:
self.SvcStop()
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
self.stop()
win32event.SetEvent(self.stop_event)
self.ReportServiceStatus(win32service.SERVICE_STOPPED)
def start(self):
app.run(host='0.0.0.0',port=4999)
# to be overridden
def stop(self):
pass
if __name__ == '__main__':
if len(sys.argv) == 1:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(fservice)
servicemanager.StartServiceCtrlDispatcher()
else:
win32serviceutil.HandleCommandLine(fservice)
I'm creating exe using command,python setup.py py2exe
but, when i try to install the service using fservice.exe --install
I get this error
Traceback (most recent call last):
File "boot_service.py", line 37, in <module>
AttributeError: 'module' object has no attribute 'Initialize
boot_service.py of py2exe
I'm using Python 2.7.6 and py2exe-0.6.9
I encountered the same problem. I don't know whether you found the solution yet
In my case, the reason would be that servicemanager is not included in the compiled package. It seems the installed servicemanager library in python issues conflict.
To solve this problem, I uninstall servicemanager if it is unused or manually copy servicemanager.pyd to folder dist and servicemager.pyc to dist\library.zip. If there is a folder named servicemanager in dist\library.zip, just delete it.
If you already had a better solution, please share it ^^
I coded out a windows service in python to write some text to a file continuously and installed it and ran it and it works fine. Now if I try to convert my python windows service script into an executable (.exe) using py2exe. The .exe installs fine as a service but when I try to start it I get the error "The server did not respond to the start ......in timely fashion". Is this got something to do with py2exe destroying information in my python script. How do I go around this? (I am trying to convert it to a .exe because I want to distribute it).
My python script is as follows:
import win32service
import win32serviceutil
import win32event
class clear_queue(win32serviceutil.ServiceFramework):
_svc_name_ = "avant"
_svc_display_name_ = "avant"
_svc_description_ = "Elegant file writer"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self,args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
def SvcDoRun(self):
import servicemanager;
fil = open("C:/Users/u/Desktop/c99/user.txt",'r+');
rc = win32event.WaitForSingleObject(self.hWaitStop, 64)
while rc != win32event.WAIT_OBJECT_0:
fil.write("george\n");
rc = win32event.WaitForSingleObject(self.hWaitStop, 64)
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(clear_queue)
Looking at the example at http://tools.cherrypy.org/wiki/WindowsService, it looks like you need to add self.ReportServiceStatus(win32service.SERVICE_STOPPED) as the final line of the SvcStop method.
below is my code that I am trying to turn into a windows service. You'll see test.py as the call it makes and all this is a short script that writes into a log file (as a test).
The code is there to make it a windows service and it does that fine, but when I run it nothing writes into the log file. Help greatly appreciated. Below is the code:
import win32service
import win32serviceutil
import win32api
import win32con
import win32event
import win32evtlogutil
import os, sys, string, time
class aservice(win32serviceutil.ServiceFramework):
_svc_name_ = "MyServiceShortName"
_svc_display_name_ = "A python test"
_svc_description_ = "Writing to a log"
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):
import servicemanager
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,servicemanager.PYS_SERVICE_STARTED,(self._svc_name_, ''))
self.timeout = 1000 #1 seconds
# This is how long the service will wait to run / refresh itself (see script below)
while 1:
# Wait for service stop signal, if I timeout, loop again
rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout)
# Check to see if self.hWaitStop happened
if rc == win32event.WAIT_OBJECT_0:
# Stop signal encountered
servicemanager.LogInfoMsg("SomeShortNameVersion - STOPPED!") #For Event Log
break
else:
#what to run
try:
file_path = "test.py"
execfile(file_path)
except:
pass
#end of what to run
def ctrlHandler(ctrlType):
return True
if __name__ == '__main__':
win32api.SetConsoleCtrlHandler(ctrlHandler, True)
win32serviceutil.HandleCommandLine(aservice)
Edit: Thought for the sake of it I'd include my test.py file's code, it has unnecessary imports but will get the job done if you run it alone.
import win32service
import win32serviceutil
import win32api
import win32con
import win32event
import win32evtlogutil
import os
logfile = open("log.txt", "a") #open file to log restart timestamp
logfile.write("\nthat's good!!!!")
logfile.close()
Okay so I figured it out and would like to come back and post in case anyone else is dealing with this, all though this was a tad unique.
You have to specify your file path if you are within a windows service, duh... but it wasn't done and I pulled my hair out for no reason.
file_path = "test.py"
should have been
file_path = r"c:\users\...\test.py"
Be careful when using '\' for windows file paths. They must be escaped like '\\' or the string must be declared as raw string ('r'). Using the unix like slash '/' separators works also but may look odd for windows users.