Python Skeleton Scripts
Jump to navigation
Jump to search
Also check out - Implementing a Standard Library - and - Skel.py
Get CLI Arguments and Read a Config File - Based on a server
Also incorporates use of Python logging module.
#!/usr/bin/env python
#
# Purpose:
#
# $Id:$
#
#-------------------------------------------------------------------------------
"""
Skeleton Python script
...
"""
#-------------------------------------------------------------------------------
import os
import sys
import getopt
import logging
#-------------------------------------------------------------------------------
from datetime import datetime
#-------------------------------------------------------------------------------
__version__ = "1.0.0"
__id__ = "@(#) skel.py [%s] 05/03/2008"
verbose_flg = False
debug_level = 0
LOGFILE = "xxxx.log"
PIDFILE = "xxxx.pid"
tables = []
log = None
pid = None
#===============================================================================
def INFO(msg):
if log: log.info(' ' + msg)
if verbose_flg: print "[xxxx] %s" % msg
#-------------------------------------------------------------------------------
def ERROR(msg):
if log: log.error(msg)
sys.stderr.write('[xxxx] %s\n' % msg)
#-------------------------------------------------------------------------------
def WARNING(msg):
if log: log.warning('*****' + msg + '*****')
if verbose_flg: print "[xxxx] %s" % msg
#===============================================================================
def init():
global log
global pid
pid = os.getpid()
log = logging.getLogger('xxx')
hdlr = logging.FileHandler(LOGFILE)
fmtr = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(fmtr)
log.addHandler(hdlr)
log.setLevel(logging.INFO)
INFO("Started processing")
if (not verbose_flg):
INFO("PID is %d" % pid)
#===============================================================================
def main():
global verbose_flg
global debug_level
try:
opts, args = getopt.getopt(sys.argv[1:], "dD:vVw?")
except getopt.error, msg:
print __doc__
return 1
try:
terminal_type = os.environ["TERM"]
except KeyError, e:
print "[xxxx] Set TERM environment variable and rerun!"
return 1
wrk_path = os.getcwd()
wrk_dir = os.path.basename(wrk_path)
data_dir = wrk_dir + '/DATA/'
pid_path = data_dir + PIDFILE
# os.chdir(data_dir)
for o, a in opts:
if o == '-d':
debug_level += 1
elif o == '-D':
debug_level = int(a)
elif o == '-v':
verbose_flg = True
elif o == '-V':
print "[xxxx] Version: %s" % __version__
return 1
elif o == '-?':
print __doc__
return 1
print "[xxxx] Working directory is %s" % os.getcwd()
if (debug_level > 0): print "[xxxx] Debugging level set to %d" % debug_level
if args:
for arg in args:
print arg
init()
return 0
#-------------------------------------------------------------------------------
if __name__ == '__main__' or __name__ == sys.argv[0]:
try:
sys.exit(main())
except KeyboardInterrupt, e:
print "[xxxx] Interrupted!"
#-------------------------------------------------------------------------------
"""
Revision History:
Date Who Description
-------- --- ------------------------------------------------------------
20031014 plh Initial implementation
Problems to fix:
To Do:
Issues:
"""
Reading CSV Files
Daemonized Server
Features:
- Threaded model.
- Serevr runs as daemon.
- Reads config file.
- Incorporates use of Python logging module.
- Start, Shutdown, Check methods.
#!/usr/bin/env python
#
# Purpose: Threaded data server implementation
#
# $Id:$
#
#---------------------------------------------------------------------
"""
Uses threaded server model
Server side: open a socket on a port, listen for
a message from a client, and accept a request and
service it.
The server spawns a thread to handle each client connection.
Threads share global memory space with main thread;
This is more portable than fork -- not yet on Windows;
This version has been extended to use the standard Python
logging module.
Add the delimiter to the INI file to allow use of alternate
delimiters in transmitted data - so data with embedded commas
can be used.
"""
#---------------------------------------------------------------------
import os
import csv
import sys
import getopt
import thread
import time
import signal
import logging
#---------------------------------------------------------------------
from socket import * # get socket constructor and constants
from datetime import datetime
#---------------------------------------------------------------------
__version__ = "1.1.1"
__id__ = "@(#) server.py [%s] 05/03/2008"
check_flg = False
daemon_flg = False
silent_flg = False
terminate_flg = False
verbose_flg = False
wait_flg = False
debug_level = 0
HOST = '' # Host server - '' means localhost
PORT = 9999 # Listen on a non-reserved port number
sockobj = None
dserver_dir = None
data_dir = None
pid_path = None
CONFIGFILE = "server.ini"
LOGFILE = "server.log"
PIDFILE = "server.pid"
tables = []
INVALID = "INVALID"
log = None
#=====================================================================
class Group:
Name = None
Idx = None
Data = None
def __init__(self, name):
self.Name = name
self.Idx = 0
self.Data = []
def __str__(self):
s = "Grp %s Len %d" % (self.Name, len(self.Data))
return s
def append(self, s):
self.Data.append(s)
def set(self):
if len(self.Data) > 0:
self.Idx = 0
else:
self.Idx = -1
#---------------------------------------------------------------------
...
#=====================================================================
def INFO(msg):
if log: log.info(' ' + msg)
if verbose_flg: print "[server] %s" % msg
#---------------------------------------------------------------------
def ERROR(msg):
if log: log.error(msg)
sys.stderr.write('[server] %s\n' % msg)
#---------------------------------------------------------------------
def WARNING(msg):
if log: log.warning('*****' + msg + '*****')
if verbose_flg: print "[server] %s" % msg
#=====================================================================
def read_config():
config_file = data_dir + CONFIGFILE
try:
f = open(config_file, 'r')
except IOError, e:
ERROR('Open failed: ' + str(e))
sys.exit(1)
definition_flg = False
while True:
line = f.readline()
if not line: break
line = line[:-1]
line = line.replace('\r','')
line = line.strip()
if (line.find("#") != -1): continue
if (line.find("[Data]") != -1):
definition_flg = True
elif (line.find("Description=") != -1):
description = line.split("=")
(name, type, delimiter) = description[1].split(":")
t = Table(name, type, delimiter)
INFO(str(t))
tables.append(t)
f.close()
#---------------------------------------------------------------------
def process(str):
if debug_level > 1: INFO("[server::process] len %d msg %s" % (l, msg))
ts = datetime.now().strftime('%Y%m%d%H%M%S')
reply = 'XXXX'
return reply
#---------------------------------------------------------------------
def sig_term(signum, frame):
"SIGTERM handler"
shutdown()
#---------------------------------------------------------------------
def shutdown():
INFO("Server shutdown at %s" % datetime.now())
for i in range(len(tables)):
tables[i].flush()
try:
os.unlink(pid_path)
except IOError, e:
ERROR('Unlink failed: ' + str(e))
sys.exit(1)
sys.exit(0)
#---------------------------------------------------------------------
def check_running():
try:
pfp = open(pid_path, 'r')
except IOError, (errno, strerror):
pfp = None
# ERROR("I/O error(%s): %s" % (errno, strerror))
except:
ERROR("Unexpected error:", sys.exc_info()[0])
raise
if pfp:
line = pfp.readline()
line = line.strip()
dserver_pid = int(line)
noProcess = 0
try:
os.kill(dserver_pid, 0)
except OSError, e:
if e.errno == 3:
noProcess = 1
else:
ERROR("kill() failed:" + str(e))
sys.exit(0)
if noProcess:
INFO("[server] Stale dserver pid file!")
pfp.close()
os.unlink(pid_path)
return None
else:
pfp.close()
return dserver_pid
return dserver_pid
else:
return None
#---------------------------------------------------------------------
def create_pidfile():
pid = os.getpid()
try:
pfp = open(pid_path, 'w')
except IOError, e:
ERROR("Open failed - " + str(e))
sys.exit(0)
pfp.write("%d" % pid)
pfp.close()
INFO("Running server with PID -> %d" % pid)
return pid
#---------------------------------------------------------------------
def become_daemon():
pid = os.fork()
if pid == 0: # In child
pid = create_pidfile()
time.sleep(1)
elif pid == -1: # Should not happen!
ERROR("fork() failed!")
time.sleep(1)
sys.exit(0)
else: # In Parent
time.sleep(1)
sys.exit(0)
time.sleep(2)
os.setsid()
return pid
#---------------------------------------------------------------------
def init():
pid = check_running()
if pid:
print "[server] Server already running! (pid = %d)" % pid
sys.exit(0)
if daemon_flg:
pid = become_daemon()
else:
pid = create_pidfile()
global log
log = logging.getLogger('dserver')
hdlr = logging.FileHandler(LOGFILE)
fmtr = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(fmtr)
log.addHandler(hdlr)
log.setLevel(logging.INFO)
INFO("Started processing")
read_config()
if (not silent_flg):
INFO("Server PID is %d" % pid)
#---------------------------------------------------------------------
def terminate():
server_pid = check_running()
if server_pid:
if (not silent_flg):
INFO("Terminating server with pid, %d" % server_pid)
os.kill(server_pid, signal.SIGTERM)
if (wait_flg):
while True:
try:
kill(server_pid, 0)
except OSError, e:
if e.errno == 3:
break
else:
ERROR("kill() failed:" + str(e))
sys.exit(0)
time.sleep(1)
return 0
#---------------------------------------------------------------------
def check():
pid = check_running()
if pid:
print "[server] Server already running! (pid = %d)" % pid
sys.exit(0)
else:
print "[server] Server not running"
#==== Socket Server ==================================================
def init_connection():
global sockobj
sockobj = socket(AF_INET, SOCK_STREAM) # make a TCP socket object
sockobj.bind((HOST, PORT)) # bind it to server port number
sockobj.listen(10) # allow upto 10 pending connects
#---------------------------------------------------------------------
def handle_client(connection): # in spawned thread: reply
while True: # read, write a client socket
try:
request = connection.recv(1024)
except:
break
if debug_level > 0: INFO('[server] Request -> "%s"' % request)
if not request: break
reply = process(request)
if debug_level > 0: INFO('[server] Reply -> "%s..."' % reply[0:30])
connection.send(reply)
connection.close()
#---------------------------------------------------------------------
def dispatcher():
while True:
# Wait for next connection,
connection, address = sockobj.accept()
INFO('Host (%s) - Connected at %s' % (address[0], datetime.now()))
thread.start_new(handle_client, (connection,))
#=====================================================================
def main():
global check_flg
global daemon_flg
global terminate_flg
global verbose_flg
global wait_flg
global debug_level
global dserver_dir
global data_dir
global pid_path
try:
opts, args = getopt.getopt(sys.argv[1:], "cdDsTvVw?")
except getopt.error, msg:
print __doc__
return 1
try:
server_dir = os.environ["SERVER_DIR"]
except KeyError, e:
print "[server] Set SERVER_DIR environment variable and rerun!"
return 1
data_dir = server_dir + '/DATA/'
pid_path = data_dir + PIDFILE
wrk_path = os.getcwd()
wrk_dir = os.path.basename(wrk_path)
os.chdir(data_dir)
for o, a in opts:
if o == '-d':
debug_level += 1
elif o == '-c':
check_flg = True
elif o == '-D':
daemon_flg = True
elif o == '-s':
tsilent_flg = True
elif o == '-T':
terminate_flg = True
elif o == '-v':
verbose_flg = True
elif o == '-V':
print "[dserver] Version: %s" % __version__
return 1
elif o == '-w':
wait_flg = True
elif o == '-?':
print __doc__
return 1
print "[server] Server working directory is %s" % os.getcwd()
if check_flg:
check()
return 0
if terminate_flg:
terminate()
return 0
if (debug_level > 0): print "[server] Debugging level set to %d" % debug_level
if args:
for arg in args:
print arg
signal.signal(signal.SIGTERM, sig_term)
init()
init_connection()
dispatcher()
return 0
#---------------------------------------------------------------------
if __name__ == '__main__' or __name__ == sys.argv[0]:
try:
sys.exit(main())
except KeyboardInterrupt, e:
print "[server] Interrupted!"
shutdown()
#---------------------------------------------------------------------
"""
Revision History:
Date Who Description
-------- --- --------------------------------------------------
20031014 plh Initial implementation
Problems to fix:
To Do:
Issues:
"""