one custom exception is definedwe will see it in use when we look at couple of the program' functions the program' main(function is used to set up some initial informationand to provide loop on each iteration the user has the chance to enter some information for the html page they want generatedand after each one they are given the chance to finish def main()information dict(name=noneyear=datetime date today(yearfilename=nonetitle=nonedescription=nonekeywords=nonestylesheet=nonewhile truetryprint("\nmake html skeleton\ "populate_information(informationmake_html_skeleton(**informationexcept cancellederrorprint("cancelled"if (get_string("\ncreate another ( / )?"default=" "lower(not in {" ""yes"})break the datetime date today(function returns datetime date object that holds today' date we want just the year attribute all the other items of information are set to none since there are no sensible defaults that can be set inside the while loop the program prints titlethen calls the populate_information(function with the information dictionary this dictionary is updated inside the populate_information(function nextthe make_html_skeleton(function is called--this function takes number of argumentsbut rather than give explicit values for each one we have simply unpacked the information dictionary if the user cancelsfor exampleby not providing mandatory informationthe program prints out "cancelledat the end of each iteration (whether cancelled or not)the user is asked whether they want to create another skeleton--if they don'twe break out of the loop and the program terminates def populate_information(information)name get_string("enter your name (for copyright)""name"information["name"]if not nameraise cancellederror(year get_integer("enter copyright year""year"information["year"] datetime date today(year true