Update page 'Day 9 homework - Sloetjes'

xuanyi.wang
2023-04-19 00:52:53 +02:00
parent 3c1047937c
commit 590ebea1ba
+129
@@ -0,0 +1,129 @@
1. Use `importlib.util.find_spec` to create a function that takes a Python module or package name, and returns the total number of bytes in the cached `.pyc` file, or the total number of bytes in the `.py` file if there is no cached bytecode. You can use the os.stat command to get the size of a file.
```
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.
```
import sys
def get_total_module_size():
"""Returns the total size of all loaded modules."""
total_size = 0
for module_name in sys.modules:
total_size += get_module_size(module_name)
return total_size
```
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)
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
def get_module_size(module_name):
spec = importlib.util.find_spec(module_name)
if spec is None:
return 0
elif spec.origin.endswith(".py"):
filename = spec.origin
elif spec.cached:
filename = spec.cached
else:
return 0
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()
```