How to Make Python Script Run as Service

How do you run a Python script as a service in Windows?

Yes you can. I do it using the pythoncom libraries that come included with ActivePython or can be installed with pywin32 (Python for Windows extensions).

This is a basic skeleton for a simple service:

import win32serviceutil
import win32service
import win32event
import servicemanager
import socket


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):
pass

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

Your code would go in the main() method—usually with some kind of infinite loop that might be interrupted by checking a flag, which you set in the SvcStop method

Run Python script as a windows service

Just a few days back I have successfully sorted out my issue I just made some changes to my code and it started working properly. I am only posting these answers for someone like me who got this issue in the future he can easily sort it out.
This is the new code:

def WriteToFile():

while True:
file = open ( "C:\\file.txt" , "w" )
now = datetime.now()
now = now.strftime("%B %d, %y %H:%M:%S")
file.write(now)

class Pythonservice(win32serviceutil.ServiceFramework):


_svc_name_ = 'PC-Service'
_svc_display_name_ = 'PC-Service'
_svc_description_ = 'Freindly Service'

@classmethod
def parse_command_line(cls):

win32serviceutil.HandleCommandLine(cls)

def __init__(self, args):

win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
socket.setdefaulttimeout(60)

def SvcStop(self):

self.stop()
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)

def SvcDoRun(self):

self.start()
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
self.main()

def start(self):
self.isrunning = True

def stop(self):
self.isrunning = False

def main(self):
WriteToFile()



if __name__ == '__main__':
Pythonservice.parse_command_line()

After these changes, I opened up a command prompt as administrator and type this command to install my service.

C:\wamp64\www\project\python\New folder>python testing.py install

I got the success message. After successful installation, I started my service using this command

C:\wamp64\www\project\python\New folder>python testing.py start

and service started successfully I confirmed from service manager as well whether my service is running or not and it was running after restarting my pc service was still in running state.

How to make a Python script run like a service or daemon in Linux

You have two options here.

  1. Make a proper cron job that calls your script. Cron is a common name for a GNU/Linux daemon that periodically launches scripts according to a schedule you set. You add your script into a crontab or place a symlink to it into a special directory and the daemon handles the job of launching it in the background. You can read more at Wikipedia. There is a variety of different cron daemons, but your GNU/Linux system should have it already installed.

  2. Use some kind of python approach (a library, for example) for your script to be able to daemonize itself. Yes, it will require a simple event loop (where your events are timer triggering, possibly, provided by sleep function).

I wouldn't recommend you to choose 2., because you would be, in fact, repeating cron functionality. The Linux system paradigm is to let multiple simple tools interact and solve your problems. Unless there are additional reasons why you should make a daemon (in addition to trigger periodically), choose the other approach.

Also, if you use daemonize with a loop and a crash happens, no one will check the mail after that (as pointed out by Ivan Nevostruev in comments to this answer). While if the script is added as a cron job, it will just trigger again.

How to create windows service using Python

Anyone facing this issue, just copy pywintypes36.dll

from Python36\Lib\site-packages\pywin32_system32

to Python36\Lib\site-packages\win32

Helpful commands:

  1. Install a service: python app.py install

  2. Uninstall a service: python app.py remove

  3. Start a service: python app.py start

  4. Update service: python app.py update

Run Python script with parameter as Windows Service

change last 2 lines with bellow code:

import servicemanager, sys
if __name__ == '__main__':
if len(sys.argv) == 1:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(PythonCornerExample)
servicemanager.StartServiceCtrlDispatcher()
else:
PythonCornerExample.parse_command_line()

How to make Python script run as service?

I use this code to daemonize my applications. It allows you start/stop/restart the script using the following commands.

python myscript.py start
python myscript.py stop
python myscript.py restart

In addition to this I also have an init.d script for controlling my service. This allows you to automatically start the service when your operating system boots-up.

Here is a simple example to get your going. Simply move your code inside a class, and call it from the run function inside MyDeamon.

import sys
import time

from daemon import Daemon


class YourCode(object):
def run(self):
while True:
time.sleep(1)


class MyDaemon(Daemon):
def run(self):
# Or simply merge your code with MyDaemon.
your_code = YourCode()
your_code.run()


if __name__ == "__main__":
daemon = MyDaemon('/tmp/daemon-example.pid')
if len(sys.argv) == 2:
if 'start' == sys.argv[1]:
daemon.start()
elif 'stop' == sys.argv[1]:
daemon.stop()
elif 'restart' == sys.argv[1]:
daemon.restart()
else:
print "Unknown command"
sys.exit(2)
sys.exit(0)
else:
print "usage: %s start|stop|restart" % sys.argv[0]
sys.exit(2)

Upstart

If you are running an operating system that is using Upstart (e.g. CentOS 6) - you can also use Upstart to manage the service. If you use Upstart you can keep your script as is, and simply add something like this under /etc/init/my-service.conf

start on started sshd
stop on runlevel [!2345]

exec /usr/bin/python /opt/my_service.py
respawn

You can then use start/stop/restart to manage your service.

e.g.

start my-service
stop my-service
restart my-service

A more detailed example of working with upstart is available here.

Systemd

If you are running an operating system that uses Systemd (e.g. CentOS 7) you can take a look at the following Stackoverflow answer.

I want to run a Python Script on a Server 24/7

If you really want to just simulate it and there is only one user. You can just return a random number each time the user make a query. It’s irrelevant how often they query it. You can put this up locally or on heroic free plan. But the fact that the user is querying every 2 seconds means lots of requests and so you may exceed the quota.

import random
from flask import Flask
import time

app = Flask(__name__)

@app.route("/")
def hello_world():
return random.randint(0,5)

Say you up it up locally on port 5000. Then, simply going to “localhost:5000” via python or browser will give you that random number.

To serve it up to multiple people, you want to have a separate thread running to generate the number. Then, the view would return the number at the URL. For example,

from flask import Flask
import random
import threading

app = Flask(__name__)

number = 0

@app.route("/")
def hello_world():
""" URL returns random number """
return str(number)


def gen_rand():
""" generating random numbers """
global number
while True:
number = random.randint(0, 5)
time.sleep(2)

if __name__ == '__main__':
# starting thread to generate the number
x = threading.Thread(target=gen_rand, daemon=True)
x.start()

# starting web server
app.run()

By default, the local webserver will start at localhost:5000, go to this URL in your browser and you will see the randomly generated numbered. You can open multiple browser tabs to see they will give same random number if refreshed within 2 seconds.

Note that using global variable is not thread-safe or process safe. You should use database or redis to update and load “number”. See this question for further discussions: Are global variables thread-safe in Flask? How do I share data between requests?.



Related Topics



Leave a reply



Submit