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.
Related
I was able to create a python service on windows 10 using this example: Is it possible to write a windows (10) service with python (standard python.org python) without compiling
Then I created a separate python file using mss to take a single screenshot of monitor 1. Everything worked fine when I run them separately. However, when i replace the text file code in the def main(self) with the screenshot code, the resulting image file is just black.
Feel like the monitor number isn't being accessed in the service, but not sure why or even if that is the issue.
Edit: The image isn't blank it's black. Updated above from blank to black.
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import mss
class AppServerSvc (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):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_,''))
self.main()
def main(self):
# Your business logic or call to any class should be here
with mss.mss() as sct:
filename = sct.shot(output="C:\\Output\\mon-{mon}-.png")
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(AppServerSvc)
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 am trying to write a Hexchat plugin in Python, which would start a server and then communicate with it using DBus and python-dbus library. Everything works fine, until I try to unload the plugin or close Hexchat (which unloads all plugins). The application freezes. It does not happen if I do not call any method using the DBus.
I tried to pinpoint the problem, so I have created a minimal example:
server.py
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
class EchoService(dbus.service.Object):
def __init__(self):
DBusGMainLoop(set_as_default=True)
self.loop = GLib.MainLoop()
bus_name = dbus.service.BusName(name='com.skontar.Echo', bus=dbus.SessionBus())
super().__init__(conn=None, object_path='/com/skontar/Echo', bus_name=bus_name)
def run(self):
self.loop.run()
#dbus.service.method(dbus_interface='com.skontar.Echo', in_signature='', out_signature='')
def quit(self):
self.loop.quit()
#dbus.service.method(dbus_interface='com.skontar.Echo', in_signature='s', out_signature='s')
def echo(self, text):
print(text)
return 'ACK'
EchoService().run()
dbus_plugin_unload_test.py
import subprocess
import time
import dbus
import hexchat
__module_name__ = 'dbus_plugin_unload_test'
__module_description__ = 'TBD'
__module_version__ = '1.0'
def get_dbus_interface():
session_bus = dbus.SessionBus()
dbus_object = session_bus.get_object(bus_name='com.skontar.Echo',
object_path='/com/skontar/Echo')
interface = dbus.Interface(object=dbus_object, dbus_interface='com.skontar.Echo')
return interface
def unload(userdata):
hexchat.prnt('Unloading {}, version {}'.format(__module_name__, __module_version__))
global interface
interface.quit()
time.sleep(1)
# raise Exception
hexchat.prnt('Loading {}, version {}'.format(__module_name__, __module_version__))
subprocess.Popen('python3 /home/skontar/Python/Examples/DBus/server.py', shell=True)
time.sleep(1)
interface = get_dbus_interface()
time.sleep(1)
interface.echo('TEST')
hexchat.hook_unload(unload)
In this example, everything works. When I try to unload the plugin or close Hexchat, server exits (so the .quit call works), but Hexchat hangs.
If I comment out both interface.echo('TEST') and interface.quit() it unloads fine, but also the plugin does not do anything useful. I have also found that if I raise Exception at the end of unload callback, everything closes "correctly", nothing hangs.
I am thinking that maybe I am supposed to do some DBus cleanup? Or am I missing some nuance of Hexchat plugin system? If I try the same with regular Python code outside the plugin system, both server and client exit just fine.
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
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.