"""https://stackoverflow.com/a/58241294/6235116""" import pefile # type: ignore from datetime import datetime import logging logging.basicConfig(level=logging.DEBUG) def get_portable_executable_info(file_path: str) -> dict: """ Return a dictionary with ProductVersion and other params of portable executable. The Portable Executable (PE) format is a file format for executables, object code, DLLs and others used in 32-bit and 64-bit versions of Windows operating systems. For non PE files this error is raised: pefile.PEFormatError: 'DOS Header magic not found.' We can use it to provide the info about the tested build to the pytest report. """ decoded_dict: dict = {} # To avoid "Local variable 'pe' might be referenced before assignment" alert. try: pe = pefile.PE(file_path) # type - class 'pefile.PE' except Exception as error: logging.error(error) return decoded_dict file_info: list = pe.FileInfo # In my case: List of lists. len==1. # The nested list contains 2 elements of class 'pefile.Structure': VarFileInfo and StringFileInfo for structure in file_info[0]: logging.debug(f"This structure type is {type(structure)}") if hasattr(structure, 'StringTable'): logging.debug("This entry CONTAINS attribute StringTable.") string_table: list = structure.StringTable # In my case:len==1. # Contains 1 element of class 'pefile.Structure' encoded_dict: dict = string_table[0].entries decoded_dict = dict( (key.decode('utf-8'), value.decode('utf-')) for key, value in encoded_dict.items()) else: logging.debug("This entry doesn't contain attribute StringTable.") # Add modification time from FILE_HEADER time_date_stamp: int = pe.FILE_HEADER.TimeDateStamp modification_time: str = str(datetime.fromtimestamp(time_date_stamp)) decoded_dict["Modification_time"] = modification_time return decoded_dict
Public There are many comments in this code - just for debugging purposes.
When you have some code in module scope, the code will be executed when someone imports that module - which makes the module completely non-reusable. Maybe it's not meant to be reusable today, but you'll have to refactor if you need to import the module later. Use if __name__ == '__main__'
to detect whether module was imported or used as a standalone script.
Better put logging setup inside if __name__ == '__main__'
section
Catching Exception
or everything means that you don't understand what the code does. So you may catch and suppress exceptions which you probably didn't want to catch at all but you weren't aware of them. It is better for your program to fail, rather then catching everything.
"Early quit" is a common pattern which reduces branching and indents in python code. Instead of writing if a: <1000 lines of code> else: <return / raise exception>
, revert the condition: if not a: <return / raise exception>
. This way the "else" clause is not needed, and program logic is straightforward: if something is wrong, quit or raise, otherwise go on.
People make typos. Here it is.
utf-
-> utf-8
This code is not really needed or may be simplified
This is a counter-example of using type hints: here they don't add any value (especially modification_time: str = str(...)
one), but make the code more polluted and less readable. Usually one should not annotate variables inside a function, unless it's hard to understand what's inside.
Create new review request