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.
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.
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:
Install a service:
python app.py install
Uninstall a service:
python app.py remove
Start a service:
python app.py start
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
Packaging a Python Script on Linux into a Windows Executable
Run Interactive Bash With Popen and a Dedicated Tty Python
How to Split a List into Equally-Sized Chunks
How to Pandas Group-By to Get Sum
How to Parse a String to a Float or Int
Pip' Is Not Recognized as an Internal or External Command
A Weighted Version of Random.Choice
How to Match a Whole Word With a Regular Expression
Pandas: How to Merge Two Dataframes on a Column by Keeping the Information of the First One
Find Size and Free Space of the Filesystem Containing a Given File
How to Upgrade Python Version to 3.7
How to Pass a Variable by Reference
Is There a Difference Between "==" and "Is"