Skip to content

Commit fe5e3f0

Browse files
committed
Initial Commit
0 parents  commit fe5e3f0

6 files changed

Lines changed: 298 additions & 0 deletions

File tree

.github/.gitignore

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# Virtual environments
7+
venv/
8+
.env/
9+
.env*/
10+
.venv/
11+
12+
# Distribution / packaging
13+
build/
14+
dist/
15+
*.egg-info/
16+
17+
# IDE / editor
18+
.vscode/
19+
.idea/
20+
21+
# OS
22+
.DS_Store
23+
Thumbs.db
24+
25+
# Logs
26+
*.log
27+
28+
# Python cache
29+
.pytest_cache/

.github/CONTRIBUTING.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Contributing
2+
3+
Thanks for your interest in improving this tiny utility! The goal is to keep it **small, dependency‑free, and easy to read**.
4+
5+
## Guiding Principles
6+
7+
- Single file (`size.py`) stays minimal
8+
- No third‑party dependencies
9+
- Cross‑platform friendliness (Windows, macOS, Linux)
10+
- Prefer clarity over micro‑optimizations unless a measurable win
11+
12+
## Good Contribution Types
13+
14+
- Documentation clarifications (README, FAQ, examples)
15+
- Reproducible bug fixes (with a short explanation of cause)
16+
- Tiny, optional flags (opened via issue first)
17+
- Improved edge‑case handling without adding complexity
18+
19+
## Please Avoid
20+
21+
- Adding packaging / installers / publishing logic
22+
- Large feature sets (interactive UI, progress bars, etc.)
23+
- Refactors that only rename things
24+
- Adding dependency managers or lock files
25+
26+
## Workflow
27+
28+
1. Fork the repo
29+
2. Create a branch: `feat/short-name` or `fix/short-name`
30+
3. Make your change (ensure script still runs with `python size.py`)
31+
4. Update docs if behavior changed
32+
5. Open a Pull Request describing the motivation
33+
34+
## Reporting Issues
35+
36+
Include:
37+
38+
- OS + Python version (`python --version`)
39+
- Example of unexpected output
40+
- If possible, the directory layout or a redacted tree
41+
42+
## Light Feature Requests
43+
44+
Open an issue first. Some acceptable minimal ideas:
45+
46+
- `--top N` to limit rows
47+
- `--min-mb X` threshold
48+
- Optional JSON output
49+
50+
## Code Style
51+
52+
- Standard library only
53+
- Keep functions short & purpose driven
54+
- Avoid premature abstraction
55+
56+
## License
57+
58+
By contributing you agree your code is released under the repository's MIT License.
59+
60+
---
61+
62+
Keep it lean. Happy hacking!

.github/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Anuj
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# python-package-size-analyzer
2+
3+
Find and list installed Python packages sorted by size (largest first) so you can quickly identify heavy dependencies to uninstall or move to a virtual environment.
4+
5+
## Why This Script?
6+
7+
- **Single-file, zero dependencies** – pure Python stdlib only.
8+
- **Fast insight** – instant overview of what is bloating your global / root Python installation.
9+
- **Actionable output** – largest packages first so you can prune immediately.
10+
- **Portable** – works anywhere standard `site` module is available (Windows, macOS, Linux).
11+
12+
> Unique Selling Point: You do _not_ need to install anything (no `pip install` step). Just run it.
13+
14+
## Features
15+
16+
- Recursively calculates total on-disk size for each package directory under all discovered `site-packages` locations
17+
- Human‑readable MB output, aligned in a clean table
18+
- Sorts automatically (largest → smallest)
19+
- Ignores unreadable files gracefully (permission or transient I/O errors)
20+
21+
## Quick Start
22+
23+
```bash
24+
python size.py
25+
```
26+
27+
Example output:
28+
29+
```
30+
Package Size (MB)
31+
----------------------------------------------------
32+
numpy 137.42
33+
pandas 62.77
34+
matplotlib 35.19
35+
scipy 31.04
36+
pip 12.11
37+
setuptools 11.45
38+
... ...
39+
```
40+
41+
(Your numbers will differ based on what is installed.)
42+
43+
## When To Use This
44+
45+
- Before committing a base Docker image – trim unnecessary global packages
46+
- Cleaning up a bloated system Python install on Windows
47+
- Auditing a CI agent or build server
48+
- Deciding which libraries to move into a virtual environment
49+
50+
## How It Works
51+
52+
The script:
53+
54+
1. Uses `site.getsitepackages()` (or falls back to `site.getusersitepackages()`)
55+
2. Walks every directory directly inside each detected `site-packages`
56+
3. Sums file sizes with `os.walk`
57+
4. Outputs a sorted table (descending by size)
58+
59+
No heuristics, no partial sampling – full recursive byte size per package directory.
60+
61+
## SEO-Friendly Keywords (contextual)
62+
63+
Python package size analyzer, list largest python packages, site-packages disk usage, python dependency bloat, remove large python packages, clean global python install, python script no dependencies, package size audit.
64+
65+
## Uninstalling Large Packages (Manual Examples)
66+
67+
Once you identify large packages you don't need globally:
68+
69+
```bash
70+
pip uninstall package_name
71+
```
72+
73+
Or prefer isolating heavy libs:
74+
75+
```bash
76+
python -m venv venv
77+
venv\Scripts\activate # Windows
78+
pip install big_package_only_when_needed
79+
```
80+
81+
## FAQ
82+
83+
**Q: Does it follow symlinks?**
84+
A: It traverses directories as presented by `os.walk`; typical site-packages rarely use large symlinks. Symlinked entries count the file they point to if resolved by the OS.
85+
86+
**Q: Will this break anything?**
87+
A: It is read-only; it only walks and sums file sizes.
88+
89+
**Q: Can I export JSON?**
90+
A: Not in this minimal version (by design). You can pipe to a file and parse manually if needed.
91+
92+
**Q: Why not use `pip list --format=...`?**
93+
A: `pip` does not provide recursive on-disk size summaries out-of-the-box.
94+
95+
## Lightweight Extensibility Ideas (Optional)
96+
97+
If you fork it, you could add:
98+
99+
- `--top N` flag
100+
- `--min-mb` filter
101+
- CSV / JSON output
102+
- Total cumulative size banner
103+
Keep changes minimal to preserve the zero-dependency ethos.
104+
105+
## Contributing
106+
107+
This is intentionally small. Feel free to open:
108+
109+
- Clear bug reports (unexpected size anomalies, cross-platform edge cases)
110+
- Tiny PRs improving readability of documentation
111+
112+
Please avoid feature bloat.
113+
114+
## License
115+
116+
MIT – see `LICENSE` file.
117+
118+
## Badge Zone
119+
120+
_(Badges kept minimal to avoid noise)_
121+
122+
![Python](https://img.shields.io/badge/Python-Stdlib%20Only-blue)
123+
![Maintenance](https://img.shields.io/badge/Maintained-Yes-green)
124+
![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)
125+
126+
---
127+
128+
If this helped you reclaim disk space, consider starring the repo so others can discover it.

output_sample.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Package Size (MB)
2+
----------------------------------------------------
3+
numpy 137.42
4+
pandas 62.77
5+
matplotlib 35.19
6+
scipy 31.04
7+
pip 12.11
8+
setuptools 11.45
9+
charset_normalizer 9.12
10+
idna 2.20
11+
requests 2.08
12+
certifi 1.69
13+
wheel 1.10
14+
urllib3 0.92
15+
six 0.83
16+
colorama 0.06
17+
... ...

size.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import os
2+
import sys
3+
import site
4+
5+
def get_package_size(path):
6+
total_size = 0
7+
for dirpath, _, filenames in os.walk(path):
8+
for f in filenames:
9+
try:
10+
fp = os.path.join(dirpath, f)
11+
if os.path.isfile(fp):
12+
total_size += os.path.getsize(fp)
13+
except OSError:
14+
pass
15+
return total_size
16+
17+
def main():
18+
# Find the site-packages directory
19+
site_packages_dirs = site.getsitepackages() if hasattr(site, "getsitepackages") else [site.getusersitepackages()]
20+
package_sizes = []
21+
22+
for site_dir in site_packages_dirs:
23+
if not os.path.isdir(site_dir):
24+
continue
25+
for item in os.listdir(site_dir):
26+
item_path = os.path.join(site_dir, item)
27+
if os.path.isdir(item_path):
28+
size_mb = get_package_size(item_path) / (1024 * 1024)
29+
package_sizes.append((item, size_mb))
30+
31+
# Sort from largest to smallest
32+
package_sizes.sort(key=lambda x: x[1], reverse=True)
33+
34+
# Print results
35+
print(f"{'Package':<40} {'Size (MB)':>10}")
36+
print("-" * 52)
37+
for name, size in package_sizes:
38+
print(f"{name:<40} {size:>10.2f}")
39+
40+
if __name__ == "__main__":
41+
main()

0 commit comments

Comments
 (0)