0

I already have a python script that runs continuously. It's very similar to this: https://github.com/walchko/Black-Hat-Python/blob/master/BHP-Code/Chapter10/file_monitor.py

Similar as in, when running it as a script, it opens a CMD which shows some data when stuff happens - it's not user-interactible so it's not mandatory that it shows (just in case someone wishes to point out that windows services can't have interfaces)

I've tried to convert it to a service. It starts for a fraction of a second and then automatically stops. When trying to start it via services.msc (instead of python script.py start) it doesn't start at all, Windows error says something like: "The service on local computer started and then stopped" which sounds just about what's happening if I try to start it with the argument.

I've tried modifying the script to allow it to run as a service - adding the skeleton I found here: Is it possible to run a Python script as a service in Windows? If possible, how?

I've also tried just getting the skeleton script above and just trying to make it run the other script with examples from here: What is the best way to call a Python script from another Python script?

Does anyone have any idea what the best course of action would be to run that script above as a service?

Thanks!

1 Answer 1

2

Edited

"...services can be automatically started when the computer boots, can be paused and restarted, and do not show any user interface." ~Introduction to Windows Service Applications

Windows services require the implementation to make a specific interface available:

So you will need to access the Windows API through Python:

You can see the example code, from Python Programming On Win32, within which Chapter 18 Services (ch18_services folder) contains a sample (SmallestService.py) demonstrating the smallest possible service written in Python:

# SmallestService.py
# 
# A sample demonstrating the smallest possible service written in Python.

import win32serviceutil
import win32service
import win32event

class SmallestPythonService(win32serviceutil.ServiceFramework):
    _svc_name_ = "SmallestPythonService"
    _svc_display_name_ = "The smallest possible Python Service"
    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        # Create an event which we will use to wait on.
        # The "service stop" request will set this event.
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)

    def SvcStop(self):
        # Before we do anything, tell the SCM we are starting the stop process.
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        # And set my event.
        win32event.SetEvent(self.hWaitStop)

    def SvcDoRun(self):
        # We do nothing other than wait to be stopped!
        win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)

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

You may need to download the appropriate pywin32 wheel for your particular python environment here: http://www.lfd.uci.edu/~gohlke/pythonlibs/#pywin32

And install it (system wide, from admin cmd prompt):

> cd \program files\python<ver>\scripts
> pip install \path\to\pywin32‑221‑cp<ver>‑cp<ver>m‑win_<arch>.whl

Or install it (per user, from regular cmd prompt):

> cd \program files\python<ver>\scripts
> pip install --user \path\to\pywin32‑221‑cp<ver>‑cp<ver>m‑win_<arch>.whl

Be sure to replace the occurences of <ver> and <arch> appropriately.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the info! And if I'd want to have the service run my other script, where and how should my code go and look like? Should I just put something like subprocess.call("script.py") under the win32serviceutil.HandleCommandLine(SmallestPythonService) ?
Try starting your script from inside the SvcDoRun() function.
I accepted your answer as it sort-of worked. The service is installing and the script starts running in the same CMD I used the "python script.py install" command on. But it's not started, and it's only working as long as I leave that CMD window open. I'm getting this: "The instance's SvcRun() method failed <Error getting traceback - traceback.print_exception() failed %2: %3" in Windows Event Viewer
You need to also adjust the code inside of __init__ and SvcStop() appropriately; Remember that this is minimal so you may need to add additional functions or more code inside of the existing functions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.