123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- import os
- import importlib.metadata
- import importlib.util
- import json
- import sys
- def calc_container(path):
- """Calculate total size of a directory or file."""
- if os.path.isfile(path):
- try:
- return os.path.getsize(path)
- except (OSError, FileNotFoundError):
- return 0
- total_size = 0
- for dirpath, dirnames, filenames in os.walk(path):
- for f in filenames:
- fp = os.path.join(dirpath, f)
- try:
- total_size += os.path.getsize(fp)
- except (OSError, FileNotFoundError):
- continue
- return total_size
- def get_package_location(package_name):
- """Get the actual location of a package's files."""
- try:
- spec = importlib.util.find_spec(package_name)
- if spec is None:
- return None
- if spec.submodule_search_locations:
- # Return the first location for namespace packages
- return spec.submodule_search_locations[0]
- elif spec.origin:
- # For single-file modules, return the file path itself
- return spec.origin
- except ImportError:
- return None
- def get_package_sizes(min_size_mb=0.1):
- """Get sizes of installed packages above minimum size threshold."""
- package_sizes = []
- # Get all installed distributions
- for dist in importlib.metadata.distributions():
- try:
- package_name = dist.metadata["Name"]
- location = get_package_location(package_name.replace("-", "_"))
- if location and os.path.exists(location):
- size = calc_container(location)
- size_mb = size / (1024 * 1024)
- if size_mb > min_size_mb:
- package_sizes.append((package_name, size))
- except Exception as e:
- print(
- f"Error processing {dist.metadata.get('Name', 'Unknown package')}: {e}"
- )
- return package_sizes
- def main():
- # Get and sort package sizes
- package_sizes = get_package_sizes()
- package_sizes.sort(key=lambda x: x[1], reverse=True)
- # Convert sizes to MB and prepare data
- table_data = [(name, size/(1024*1024)) for name, size in package_sizes]
- total_size = sum(size for _, size in package_sizes)/(1024*1024)
- # Check if --json flag is present
- if "--json" in sys.argv:
- try:
- output_file = sys.argv[sys.argv.index("--json") + 1]
- json_data = {
- "packages": [{
- "name": name,
- "size_mb": round(size, 2)
- } for name, size in table_data],
- "total_size_mb": round(total_size, 2)
- }
- with open(output_file, 'w') as f:
- json.dump(json_data, f, indent=2)
- print(f"JSON data written to {output_file}")
- return
- except IndexError:
- print("Error: Please provide a filename after --json")
- sys.exit(1)
- except Exception as e:
- print(f"Error writing JSON file: {e}")
- sys.exit(1)
- # Original table output code
- max_name_width = max(len(name) for name, _ in table_data)
- max_name_width = max(max_name_width, len("Package"))
- print(f"\n{'Package':<{max_name_width}} | Size (MB)")
- print("-" * max_name_width + "-+-" + "-" * 10)
- for name, size in table_data:
- print(f"{name:<{max_name_width}} | {size:>8.2f}")
- print(f"\nTotal size: {total_size:.2f} MB\n")
- if __name__ == "__main__":
- main()
|