isn' relevant to parsing as suchand in any case it can be downloaded from the book' web site the parsing is done in single function that accepts an open file object (file)and boolean (lowercase_keysthat has default value of false the function uses two regexes and populates dictionary (key_valuesthat it returns we will look at the regexes and then the code that parses the file' lines and that populates the dictionary ini_header re compile( "^\[[^]]+\]$"although we want to ignore ini headers we still need to identify them the regex makes no allowance for leading or trailing whitespace--this is because we will be stripping whitespace from each line that is read so there will never be any the regex itself matches the start of the linethen an open bracketthen one or more characters (but not close brackets)then close bracketand finallythe end of the line key_value_re re compile( "^(? \ +)\ *=\ *(? *)$"keyvalue regex the key_value_re regex allows for whitespace around the signbut we only capture the actual key and value the value is quantified by so can be empty alsowe use named captures since these are clearer to read and easier to maintain because they are not affected by new capture groups being added or removed--something that would affect us if we used numbers to identify the capture groups key_values {for linoline in enumerate(filestart= )line line strip(if not line or line startswith("#")continue key_value key_value_re match(lineif key_valuekey key_value group("key"if lowercase_keyskey key lower(key_values[keykey_value group("value"elseini_header ini_header match(lineif not ini_headerprint("failed to parse line { }{ }format(linoline)enumerate(function we process the file' contents line by lineusing the built-in enumerate(function to return -tuples of the line number (starting from as is traditional when dealing with text files)and the line itself we strip off whitespace so that