diff --git a/Day 9 homework - Sloetjes.md b/Day 9 homework - Sloetjes.md index 1a1d93a..dc66076 100644 --- a/Day 9 homework - Sloetjes.md +++ b/Day 9 homework - Sloetjes.md @@ -4,119 +4,27 @@ import importlib.util import os -def get_module_size(module_name): - """Returns the size of a module's bytecode file or source file.""" - spec = importlib.util.find_spec(module_name) - if spec is None: - return 0 - if spec.cached_bytecode: - return os.stat(spec.cached_bytecode).st_size - elif spec.origin: - return os.stat(spec.origin).st_size - return 0 -``` - -2. Create another function that uses the last function to see how many bytes are in all the modules listed in sys.modules. -``` - -``` - -3. Run your Python interpreter like you would normally, using Jupyter, and run the last function. How many bytes are being used? - -4. Now, run the same function, but start the Python interpreter in Powershell (Windows), or the regular shell (MacOS/Linux) with the `-E` flag, which ignores environment variables and should only load the modules that came with the original build of the Python interpreter. How many bytes are being used now? - -5. With only the `sys` module loaded, look at the `sys.modules` dict. What is the type of the value of the `os` key? - -6. Import the os module. What happens when you type `type(os)`? - -7. Restart the Python interpreter. Can you figure out how to call `os.getlogin()` without saying `import os`? -``` -login = __import__('os').getlogin() -print(login) -``` -8. If you can, explain why this works and quote the relevant sections of section 5 in the language reference. - -9. Using the functions you created above and `sys.modules`, create a module designed to be run from the command line (`python -m myscript.py`) that generates a report summarizing the module environment, and break down the percentages of bytecode modules, DSO modules (these have `__file__` end in `.so` or `.dll`), and normal python code. - -``` -import sys -import os.path - -# Classify each module based on its __file__ attribute -bytecode_modules = [] -dso_modules = [] -source_modules = [] -for module_name, module in sys.modules.items(): - if module is None or not hasattr(module, '__file__'): - continue - filename = module.__file__ - if filename.endswith('.pyc'): - bytecode_modules.append(module_name) - elif filename.endswith(('.so', '.dll')): - dso_modules.append(module_name) +def get_module_path(module_name): + module = sys.modules.get(module_name) + if module is None: + return None + if hasattr(sys, 'frozen') and sys.frozen: + # Module is part of a frozen binary or executable + return sys.executable + elif hasattr(module, '__file__'): + # Module has a __file__ attribute + return module.__file__ else: - source_modules.append(module_name) - -# Calculate the percentages of each module type -total_modules = len(sys.modules) -bytecode_percent = len(bytecode_modules -``` - -10. Add a feature to the script which looks at `__file__` for each module, trims the filename to get the directory name, then prints out a histogram of how many modules are in each directory name. If you can't find a text histogram output library in anaconda's built-in modules, just print out the `*` character for each module. -``` -import importlib.util -import os -import sys + # Module doesn't have a __file__ attribute + return None def get_module_size(module_name): - spec = importlib.util.find_spec(module_name) - if spec is None: + module_path = get_module_path(module_name) + if module_path is None: return 0 - elif spec.origin.endswith(".py"): - filename = spec.origin - elif spec.cached: - filename = spec.cached + if module_path.endswith('.pyc'): + filename = module_path[:-1] else: - return 0 + filename = module_path return os.stat(filename).st_size - -def get_module_sizes(): - sizes = {} - for module_name in sys.modules: - sizes[module_name] = get_module_size(module_name) - return sizes - -def summarize_modules(): - total_size = 0 - bytecode_size = 0 - dso_size = 0 - python_size = 0 - module_counts = {} - for module_name, size in get_module_sizes().items(): - if size == 0: - continue - total_size += size - if module_name.endswith("pyc"): - bytecode_size += size - elif hasattr(sys.modules[module_name], "__file__"): - file_name = sys.modules[module_name].__file__ - if file_name.endswith((".so", ".dll")): - dso_size += size - elif file_name.endswith(".py"): - python_size += size - - directory = os.path.dirname(os.path.abspath(file_name)) - module_counts[directory] = module_counts.get(directory, 0) + 1 - - print(f"Total module size: {total_size} bytes") - print(f"Bytecode modules: {bytecode_size/total_size*100:.2f}%") - print(f"DSO modules: {dso_size/total_size*100:.2f}%") - print(f"Python modules: {python_size/total_size*100:.2f}%") - - print("Module directory histogram:") - for directory, count in module_counts.items(): - print(f"{directory}: {'*' * count}") - -if __name__ == "__main__": - summarize_modules() ``` \ No newline at end of file