Improving the main() function
On line 42, we define the main() function that now accepts a new argument that we will call in_file. This argument, as defined by the docstring, is a string path to the setupapi.dev.log file to be analyzed:
042 def main(in_file):
043 """
044 Main function to handle operation
045 :param in_file: string path to Windows 7 setupapi.dev.log
046 :return: None
047 """
On line 48, we perform a validation of the input file to ensure that the file path and file exists using the os.path.isfile() function, which will return true if it is a file that's accessible by the script. As an aside, the os.path.isdir() function can be used to perform the same style of validation for directories. These functions work well with string inputs that represent either absolute or relative paths:
048 if os.path.isfile(in_file):
If the file path is valid, we print the version of the script. This time, we use the .format() method to create our desired string. Let's look at the formatters we've used on lines 49 and 51, starting with a colon to define our specified format. The caret (^) symbol indicates that we want to center the supplied object and have the padding to a minimum of 22 characters, using equal signs as padding. For example, the string Hello World! would be sandwiched between five equal signs on both sides. In the case of our script, we supply an empty string as the object to format because we only want 22 equal signs to create visual separation from the output.
On line 50, the .format() method is used to print the script name and version strings, as follows:
049 print('{:=^22}'.format(''))
050 print('{} {}'.format('SetupAPI Parser, v', __date__))
051 print('{:=^22} \n'.format(''))
On line 52, we call the parse_setupapi() function and pass the setupapi.dev.log file, which we know is available. This function returns a list of USB entries, with one entry per discovered device. Each entry in device_information consists of two elements, that is, the device name, and the associated date value. On line 53, we iterate through this list using a for loop and feed each entry to the print_output() function on line 54:
052 device_information = parse_setupapi(in_file)
053 for device in device_information:
054 print_output(device[0], device[1])
On line 55, we handle the case where the provided file is not valid. This is a common way to handle errors that have been generated from invalid paths. Within this condition, we print on line 56 that the input is not a valid file.
On line 57, we call sys.exit() to quit the program with an error of one. You may place any number here; however, since we defined this as one, we will know where the error was raised at exit:
055 else:
056 print('Input is not a file.')
057 sys.exit(1)