Last active
June 1, 2019 15:58
-
-
Save tstone2077/4532404 to your computer and use it in GitHub Desktop.
Template for a python tool. This template supports:* running on the command line or importing* alternate return codes* argument parsing and validating* logging
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# vim: set fileencoding=utf-8 | |
import argparse | |
import logging | |
import os | |
import sys | |
import json | |
# ------------------- | |
__doc__ = """ | |
Enter description here | |
""" | |
__author__ = 'Thurston Stone' | |
__versioninfo__ = (0, 1, 0) | |
__version__ = '.'.join(map(str, __versioninfo__)) | |
INVALID_USAGE_RETURN_CODE = 2 | |
UNCAUGHT_EXCEPTION = 3 | |
SCRIPT_FILE = os.path.basename(os.path.abspath(__file__)) | |
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) | |
class UsageError(Exception): | |
""" Exception class when the file is used incorrectly on the command line | |
""" | |
def __init__(self, parser, error): | |
self.parser = parser | |
self.error = error | |
def __str__(self): | |
return "%s\nERROR: %s" % (self.parser.format_usage(), self.error) | |
def ValidateArgs(argv): | |
""" | |
Function: validateArgs(): | |
will validate the command line arguments and options passed. | |
it returns opts,args | |
""" | |
# First, create a parser to check for the config file. | |
# If a config file argument exists, then we will want to | |
# use it to inform the main parser | |
confParser = argparse.ArgumentParser(add_help=False) | |
confParser.add_argument("-c", | |
"--config-file", | |
type=argparse.FileType("r"), | |
help="Path to file containing configuration data.") | |
args = confParser.parse_known_args()[0] | |
formatter = argparse.RawTextHelpFormatter | |
parser = argparse.ArgumentParser(description=__doc__, parents=[confParser], | |
formatter_class=formatter) | |
# Set defaults here instead of in the add_argument function. | |
# This is to prevent the add_function default from overriding | |
# the defaults set in the set_defaults functions. | |
defaults = { | |
'verbose': 'ERROR', | |
} | |
if args.config_file: | |
# Parse the config file as a json file | |
jsonInput = json.load(args.config_file) | |
# Edit the defaults dictionary based on config contents | |
for name,value in jsonInput.items(): | |
defaults[name.replace("-", "_")] = value | |
# set the defaults from the dictionary | |
parser.set_defaults(**defaults) | |
# general options | |
parser.add_argument("-v", | |
"--verbose", | |
# default="ERROR", do not set default here. | |
# required=True, do not set required here. | |
const="INFO", | |
nargs="?", | |
help="Level of verbose output to Display to stdout" | |
"(DEBUG, INFO, WARNING, ERROR, CRITICAL, FATAL)") | |
args = parser.parse_args(argv[1:]) | |
error = None | |
""" | |
Place any error checking here. If an error occurred, set the error | |
variable. | |
""" | |
# check required elements here | |
if args.verbose is None: | |
error = "verbose must be set." | |
if error is not None: | |
raise UsageError(parser, error) | |
return args | |
class Application(object): | |
def __init__(self): | |
logging.debug("Initializing Application...") | |
def Run(self): | |
logging.debug("Running Application...") | |
def Main(argv): | |
""" | |
The main function. This function will run if the command line is called as | |
opposed to this file being imported. | |
""" | |
args = ValidateArgs(argv) | |
level = getattr(logging, args.verbose.upper()) | |
logging.basicConfig(level=level, | |
format='%(module)s(%(lineno)d)|%(asctime)s|' + | |
'%(threadName)s|%(levelname)s| %(message)s') | |
logging.debug("Python %s" % sys.version) | |
app = Application() | |
app.Run() | |
return 0 | |
# if this program is run on the command line, run the main function | |
if __name__ == '__main__': | |
showTraceback = False | |
if '--show-traceback' in sys.argv: | |
showTraceback = True | |
del sys.argv[sys.argv.index('--show-traceback')] | |
try: | |
returnCode = Main(sys.argv) | |
except Exception as e: | |
if showTraceback: | |
raise | |
print("Uncaught Exception: %s: %s" % (type(e), e)) | |
returnCode = UNCAUGHT_EXCEPTION | |
sys.exit(returnCode) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment