Skip to content

Instantly share code, notes, and snippets.

@DS256
Created January 30, 2022 14:57
Show Gist options
  • Save DS256/b2d9293563254f6bd1b22ca5f5b670a7 to your computer and use it in GitHub Desktop.
Save DS256/b2d9293563254f6bd1b22ca5f5b670a7 to your computer and use it in GitHub Desktop.
Simple Python Template With Argument Parsing and Logging
#!/usr/bin/env python
# TEMPLATE_1.PY
# This program template was created to be simple single program.
# I didn't want to get around to having the complexity of a Python project.
# I am greatful to the following contributors who I stole code from ;-)
# - https://gist.github.com/calebrob6/eb98725187425c527567#file-template-py
# - https://gist.github.com/nafeu/e513e23b6b343ef896e4cccd4430b428
import sys,os
import time
import argparse
import logging
__program__ = "Template"
__author__ = "John Doe"
__copyright__ = "Copyright 2022, John Doe"
__credits__ = ["John Doe"]
__license__ = ""
__version__ = "1.0"
__maintainer__ = "John Doe"
__email__ = "[email protected]"
__status__ = "Development"
# The following special names are defined because I could not find an import
# of return codes when terminating the program. I haven't tried it yet, but
# __FAILURE__ should be able to be trapped in a shell script.
__success__ = 0
__failure__ = 1
#************************************************************************************************
# https://docs.python.org/3/library/argparse.html
def doArgs(argList, name):
parser = argparse.ArgumentParser(description=name)
parser.add_argument('-v', "--verbose", action="store_true", help="Enable verbose information", default=False)
parser.add_argument('-d', "--debug", action="store_true", help="Enable debugging", default=False)
parser.add_argument('--input', action="store", dest="inputFn", type=str, help="Input file name", required=False)
parser.add_argument('--output', action="store", dest="outputFn", type=str, help="Output file name", required=False)
return parser.parse_args(argList)
#************************************************************************************************
# Mainline Function Called From End of Program
#************************************************************************************************
def main():
startTime=time.time() # Used to calculate run-time of the program
progName = __program__ # I distinquish between the program name and
runName = sys.argv[0] # the name it may run under for testing.
# Start Logging
# Logging levels explained https://www.logicmonitor.com/blog/python-logging-levels-explained
# See https://docs.python.org/3/howto/logging-cookbook.html for other examples
# I haven't figured out a way to set 'logging.DEBUG' outside of the basicConfig call. However,
# I wanted to use it because it seemed easier than logging.logger()
logging.basicConfig(format="%(asctime)s:%(levelname)s:%(message)s",level=logging.DEBUG)
# logging.basicConfig(filename=runName+".log",format="%(asctime)s:%(levelname)s:%(message)s",level=logging.DEBUG)
# Parse Arguements
args = doArgs(sys.argv[1:], progName)
# Process/Validate Passed Arguements
# --verbose Provide some runtime information.
verbose = args.verbose
# --debug Provide information using for debugging
global debug
debug = args.debug
if debug: verbose = True
if verbose: logging.info("Started "+progName+" running as "+runName)
if debug: logging.debug("*** DEBUG MODE ***")
# --input inputFn NOT USED IN TEMPLATE PLACE HOLDER
input_specified = False # Indicates whether an INPUT FILE has been specified
if (args.inputFn is not None):
input_specified = True
inputFn = args.inputFn
if not os.path.isfile(inputFn):
logging.critical("Input file "+inputFn+" doesn't exist, exiting")
return __failure__
# --output outputFn NOT USED IN TEMPLATE PLACE HOLDER
output_specified = False # Indicates whether an OUTPUT file has been specified.
if (args.outputFn is not None):
outputFn = args.outputFn
output_specified = True
outputBase = os.path.dirname(outputFn)
if outputBase!='' and not os.path.exists(outputBase):
logging.critical("Output directory "+outputBase+" doesn't exist, exiting")
return __failure__
else:
if verbose: logging.info("Output to "+outputFn)
##### START OF MAINLINE CODE ####
##### END OF MAINLINE CODE ####
if verbose: logging.info("Finished in %0.4f seconds" % (time.time() - startTime) )
return __success__
#************************************************************************************************
if __name__ == '__main__':
rtn=main()
if debug: logging.debug("Main() return value "+str(rtn))
sys.exit(rtn) # User sys.exit() since it seems to invoke cleanup code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment