From d06a051cc196b035554fdfa732de49a108b7da27 Mon Sep 17 00:00:00 2001 From: "xuanyi.wang" Date: Wed, 19 Apr 2023 19:17:41 +0200 Subject: [PATCH] Update page 'Day 10 homework - Sloetjes ' --- Day 10 homework - Sloetjes .md | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Day 10 homework - Sloetjes .md diff --git a/Day 10 homework - Sloetjes .md b/Day 10 homework - Sloetjes .md new file mode 100644 index 0000000..744edd3 --- /dev/null +++ b/Day 10 homework - Sloetjes .md @@ -0,0 +1,83 @@ +1. Run the module-inspector script, and fix any problems that prevent it from running. + +2. Look at the output. Notice that some of the module names seem similar, and are cached via two different loader methods. + +3. Based on what you see from the module-inspector script, modify your answer from question 10 from the day 9 homework, so the similar module names aren't counted multiple times. +``` +import sys +import os +from collections import defaultdict + +def get_module_stats(): + byte_count = 0 + dso_count = 0 + py_count = 0 + module_files = set() + module_dirs = defaultdict(int) + + for name, module in sys.modules.items(): + if module is None: + continue + + filename = getattr(module, '__file__', None) + if not filename: + continue + + if filename.endswith('.pyc') or filename.endswith('.pyo'): + byte_count += 1 + elif os.path.splitext(filename)[-1] in ('.so', '.dll'): + dso_count += 1 + else: + py_count += 1 + + # check if module filename has been counted already + if filename not in module_files: + module_files.add(filename) + + module_dir = os.path.dirname(os.path.abspath(filename)) + module_dirs[module_dir] += 1 + + total_count = byte_count + dso_count + py_count + + byte_percent = byte_count / total_count * 100 + dso_percent = dso_count / total_count * 100 + py_percent = py_count / total_count * 100 + + return { + 'bytecode': { + 'count': byte_count, + 'percent': byte_percent, + }, + 'DSO': { + 'count': dso_count, + 'percent': dso_percent, + }, + 'python': { + 'count': py_count, + 'percent': py_percent, + }, + 'total': total_count, + 'module_dirs': module_dirs, + } + +def print_module_stats(): + stats = get_module_stats() + + print(f'Total modules: {stats["total"]}') + print(f'Bytecode modules: {stats["bytecode"]["count"]} ({stats["bytecode"]["percent"]:.2f}%)') + print(f'DSO modules: {stats["DSO"]["count"]} ({stats["DSO"]["percent"]:.2f}%)') + print(f'Python modules: {stats["python"]["count"]} ({stats["python"]["percent"]:.2f}%)') + + print('\nModule directory histogram:') + for module_dir, count in sorted(stats['module_dirs'].items(), key=lambda x: x[1], reverse=True): + print(f'{module_dir}: {"*" * count}') + +if __name__ == '__main__': + print_module_stats() +``` +By using a set called `module_files` to keep track of the filenames of the modules that we have counted so far. Before counting a module, we check if its filename has been counted already. If it has, we skip the module and move on to the next one. This ensures that similar module names are counted only once. + +4. Inspect the `__loader__` attribute of each entry in the `sys.modules` dict. Can you find an attribute of `__loader__` which reliably tells you if the loader is source, builtin, or extension? +5. Add `import pandas` to the top of the module-inspector script and re-run it. Notice that many of the pandas modules are not loaded using the `SourceFileLoader`. Can you explain why these modules are different? + +Extra credit: use the freeze utility to turn the module-inspector script into a real app. \ No newline at end of file