Update page 'Day 9 homework - Sloetjes'

xuanyi.wang
2023-04-19 04:37:47 +02:00
parent b704965bd1
commit 935d0d9f2f
+17 -109
@@ -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()
```