Python script as Windows service + on schedule + logging

  • Testing on Windows 7, 2008, 2012

Note:
In line: timer = schedule.every(10).seconds, you sets schedule time.
In line: timer.do(test1), where test1 — this your main script(program) to execute schedule task.
In line: _svc_name_ = «mytest-service» — this is your service name.
In line: _svc_display_name_ = «mytest-service» — this is your service display name in Windows service list.

Edit by yourself and save this code to file serv.py:

import win32serviceutil  # https://sourceforge.net/projects/pywin32/files/pywin32/Build%20220/pywin32-220.win32-py3.4.exe/download
import win32service
import win32event
import servicemanager
import socket
import time
import logging
import logging.handlers
import schedule  # https://pypi.python.org/pypi/schedule
from mytest import test1

# Managaement of service
# python.exe serv.py install | remove | start | stop | help

# Sets log file path.
log_file ="c:\\output.log";

# Return a logger with the specified name.
mylogger = logging.getLogger("MyLogger")

# Sets the threshold for this logger to lvl. Logging messages which are less severe than lvl will be ignored.
mylogger.setLevel(logging.DEBUG)

# Sets rotation parameters of disk log files
# https://docs.python.org/3.4/library/logging.handlers.html#rotatingfilehandler
handler = logging.handlers.RotatingFileHandler(log_file, maxBytes=10485760, backupCount=2)

# Sets format of record in log file
formatter = logging.Formatter('%(asctime)s - %(module)-10s - %(levelname)-8s %(message)s', '%d-%m-%Y %H:%M:%S')
handler.setFormatter(formatter)

# Adds the specified handler to logger "MyLogger"
mylogger.addHandler(handler)

class WinService(win32serviceutil.ServiceFramework):
    _svc_name_ = "mytest-service"    # service name
    _svc_display_name_ = "mytest service"    # display service name

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.stop_event = win32event.CreateEvent(None, 0, 0, None)
        socket.setdefaulttimeout(60)
        self.stop_requested = False

    # stop command service
    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.stop_event)
        mylogger.info("*** STOPPING SERVICE ***\n")
        self.stop_requested = True

    # start command service
    def SvcDoRun(self):
        servicemanager.LogMsg(
            servicemanager.EVENTLOG_INFORMATION_TYPE,
            servicemanager.PYS_SERVICE_STARTED,
            (self._svc_name_, '')
        )
        mylogger.info("*** STARTING SERVICE ***\n")
        # run main process
        self.main()

    # main process
    def main(self):
        mylogger.info("... STARTING SCHEDULE PROCESS ...\n")
        # schedule time for our task(program)
        # For example, I use "test1" procedure from "mytest" own module
        timer = schedule.every(10).seconds
        timer.do(test1)
        # run main loop for schedule process while service runs
        while not self.stop_requested:
            # execute task on schedule
            schedule.run_pending()
            time.sleep(1)
        return

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

For example, I use simple procedure «test1» from file mytest.py:

import logging

# Return a logger with the specified name.
mylogger = logging.getLogger("MyLogger")

def test1():
    mylogger.info("Run!\n")

Create Windows service which will run procedure «test1». For this you should call command line (CMD) and run this command:

python.exe serv.py install

serv_install

Next step, start this service:

python.exe serv.py start

— Or start service from Windows service list
serv_servicelist

After some time try stopping service and see log file:

python.exe serv.py stop

— Or stop service from Windows service list

In log file you can see following info:
19-07-2016 10:34:20 — serv       — INFO     *** STARTING SERVICE ***

19-07-2016 10:34:20 — serv       — INFO     … STARTING SCHEDULE PROCESS …

19-07-2016 10:34:30 — mytest     — INFO     Run!

19-07-2016 10:34:40 — mytest     — INFO     Run!

19-07-2016 10:34:50 — mytest     — INFO     Run!

19-07-2016 10:35:00 — mytest     — INFO     Run!

19-07-2016 10:35:10 — mytest     — INFO     Run!

19-07-2016 10:35:14 — serv       — INFO     *** STOPPING SERVICE ***

P.s.: Have a good day!

Реклама

How to check port access by Python

from socket import socket, gethostbyname, AF_INET, SOCK_STREAM
import time

'''
Function to check the availability of computer by port.
host - IP-address or computer name
port - port number
count - number of times to repeat the request on port
timeout - amount of seconds between echo requets on port
'''


def is_port(host="127.0.0.1", port=1433, count=1, timeout=1):
checked = False
    for i in range(count):
        ip = gethostbyname(host)
        sock = socket(AF_INET, SOCK_STREAM)
        result = sock.connect_ex((ip, port))
        if result == 0:
            print("*** port is available! ***")
            checked = True
            break
        sock.close()
        time.sleep(timeout)
        if not checked:
            print("*** port is NOT available! ***")
   return checked 

How ping computer on Python?

This python code will do it!

import subprocess
import re

'''
Function to check the availability of the network computer.
Support computer on Windows
    host - name or ip remote computer (default 127.0.0.1)
    n - number of requests sent to the echo (default 3)
'''


def is_ping(host='127.0.0.1', n='3'):
    # call Windows utility Ping
    ping = subprocess.Popen(["ping", "-n", n, host], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    # get echo answer from remote computer
    out, error = ping.communicate()
    # decode string in utf-8
    msg = out.decode('utf-8')
    # availability status is True
    if re.findall("Reply from", msg):
        l = msg.split('\r\n')
        print(l)
        # get last availability status
        for el in l:
            if re.findall("Reply from", el):
                state = el
                print(el)
        # last availability status is True
        if re.findall("Reply from \d+.\d+.\d+.\d+: bytes=\d+ time<\d+ms TTL=\d+", state):
            print('*** {0} is available ***'.format(host))
            return True
        # last availability status is False
        else:
            print('*** {0} is unavailable ***'.format(host))
            return False
    # availability status is False
    else:
        print('*** {0} is unavailable ***'.format(host))
        return False

For example, save is_ping in file pinger.py and calling in python console:

from pinger import is_ping
is_ping('192.168.1.10', 4)

----------------------------------------
Reply from 192.168.1.10: bytes=32 time<1ms TTL=128
Reply from 192.168.1.10: bytes=32 time<1ms TTL=128
Reply from 192.168.1.10: bytes=32 time<1ms TTL=128
Reply from 192.168.1.10: bytes=32 time<1ms TTL=128
*** 192.168.1.10 is available ***
True