Advanced Python Programs | IT Developer
IT Developer

Advanced Python Programs



Share with a Friend

Introduction and Setup

Build a Virtual Environment Manager using venv and subprocess - Advanced Python Program

Prereqs: Python 3.10+,

pip install psutil black flake8 isort twine build rich

(some scripts also use colorama or tomllib on <3.11).

 

Virtual Environment Manager

File Name : venvman.py

Description: Create/list/remove virtual environments in a configurable folder.

Usage:

 

python venvman.py create myenv

python venvman.py list

python venvman.py remove myenv

#!/usr/bin/env python3 import argparse, os, shutil, subprocess, sys from pathlib import Path ROOT = Path.home() / ".venvs" ROOT.mkdir(exist_ok=True) if __name__ == "__main__": ap = argparse.ArgumentParser() sub = ap.add_subparsers(dest="cmd", required=True) p_create = sub.add_parser("create"); p_create.add_argument("name") p_rm = sub.add_parser("remove"); p_rm.add_argument("name") sub.add_parser("list") args = ap.parse_args() if args.cmd == "create": target = ROOT / args.name if target.exists(): print("Already exists", file=sys.stderr); sys.exit(1) subprocess.check_call([sys.executable, "-m", "venv", str(target)]) print("Created:", target) print("Activate:") if os.name == "nt": print(fr"{target}\\Scripts\\activate") else: print(fr"source {target}/bin/activate") elif args.cmd == "list": for p in sorted(ROOT.iterdir()): if (p / ("Scripts" if os.name=="nt" else "bin") / "python").exists(): print(p.name) elif args.cmd == "remove": target = ROOT / args.name shutil.rmtree(target, ignore_errors=True) print("Removed:", target)

Output

 
OUTPUT 1 :

D:\py_prog>python venvman.py create myenv

Created: C:\Users\.venvs\myenv

Activate:

C:\Users\.venvs\myenv\\Scripts\\activate

 

D:\py_prog>python venvman.py list

 

D:\py_prog>python venvman.py remove myenv

Removed: C:\Users\.venvs\myenv

Virtual Environment Manager - Step by Step Explanation

File Name : venvman.py

Description: Create/list/remove virtual environments in a configurable folder.

Usage:

 

python venvman.py create myenv

python venvman.py list

python venvman.py remove myenv

#!/usr/bin/env python3 """ venvman.py - Minimal virtual environment manager (cross-platform) Commands: create [--python /path/to/python] Create a new venv under $VENV_HOME or ~/.venvs list List all venvs remove Delete a venv info Show interpreter/build/site-packages path Print the venv path run -- Run a command inside the venv pip Run pip inside the venv (install/uninstall/show/…) freeze Show pip freeze for that venv export -o requirements.txt Save pip freeze to a file import -r requirements.txt Install from a requirements file Environment: VENV_HOME Root directory for environments (default: ~/.venvs) """ from __future__ import annotations import argparse import os import shutil import subprocess import sys from pathlib import Path from typing import List # ---------- Config & cross-platform constants ---------- ROOT = Path(os.environ.get("VENV_HOME", Path.home() / ".venvs")) BIN_DIR = "Scripts" if os.name == "nt" else "bin" PY_NAME = "python.exe" if os.name == "nt" else "python" PIP_NAME = "pip.exe" if os.name == "nt" else "pip" # ---------- Helpers ---------- def venv_path(name: str) -> Path: return ROOT / name def venv_python(name: str) -> Path: return venv_path(name) / BIN_DIR / PY_NAME def venv_pip(name: str) -> Path: return venv_path(name) / BIN_DIR / PIP_NAME def ensure_exists(name: str) -> None: if not venv_python(name).exists(): sys.exit(f"[!] Environment '{name}' not found at {venv_path(name)}") def check_call(cmd: List[str], **kwargs) -> None: subprocess.check_call(cmd, **kwargs) # ---------- Commands ---------- def cmd_create(args: argparse.Namespace) -> None: ROOT.mkdir(parents=True, exist_ok=True) target = venv_path(args.name) if target.exists(): sys.exit(f"[!] Already exists: {target}") py = args.python or sys.executable print(f"[*] Creating venv '{args.name}' with {py} ...") check_call([py, "-m", "venv", str(target)]) print(f"[+] Created: {target}") print("[i] Activate manually:") if os.name == "nt": print(fr" {target}\Scripts\activate") else: print(f" source {target}/bin/activate") def cmd_list(_args: argparse.Namespace) -> None: if not ROOT.exists(): print("(no environments)") return rows = [] for p in sorted(ROOT.iterdir()): interp = p / BIN_DIR / PY_NAME if interp.exists(): rows.append((p.name, interp)) if not rows: print("(no environments)") return width = max(len(n) for n, _ in rows) for name, interp in rows: print(f"{name:<{width}} -> {interp}") def cmd_remove(args: argparse.Namespace) -> None: path = venv_path(args.name) if not path.exists(): print(f"[i] Not found: {path}") return print(f"[*] Removing {path} ...") shutil.rmtree(path) print("[+] Removed.") def cmd_info(args: argparse.Namespace) -> None: ensure_exists(args.name) py = str(venv_python(args.name)) # Ask the venv's python to describe itself in JSON (robust across platforms) out = subprocess.check_output( [ py, "-c", ( "import sys,sysconfig,platform,site,json;" "print(json.dumps({" "'version':sys.version.replace('\\n',' ')," "'implementation':platform.python_implementation()," "'executable':sys.executable," "'prefix':sys.prefix," "'platform':sys.platform," "'paths':sysconfig.get_paths()," "'site':site.getsitepackages() if hasattr(site,'getsitepackages') else []" "}))" ), ], text=True, ) import json info = json.loads(out) print(f"Name: {args.name}") print(f"Path: {venv_path(args.name)}") print(f"Executable: {info['executable']}") print(f"Impl/Ver: {info['implementation']} {info['version']}") print(f"Platform: {info['platform']}") print("Paths:") for k, v in info["paths"].items(): print(f" {k:<12} {v}") if info["site"]: print("Site-packages:") for sp in info["site"]: print(f" - {sp}") def cmd_path(args: argparse.Namespace) -> None: ensure_exists(args.name) print(venv_path(args.name)) def cmd_run(args: argparse.Namespace) -> None: ensure_exists(args.name) if not args.cmd: sys.exit("[!] Provide a command after --, e.g. venvman run myenv -- python -V") env = os.environ.copy() env["PATH"] = str(venv_path(args.name) / BIN_DIR) + os.pathsep + env.get("PATH", "") env["VIRTUAL_ENV"] = str(venv_path(args.name)) # On Windows, prefer the venv's Python if user asked to run "python" rc = subprocess.call(args.cmd, env=env) sys.exit(rc) def cmd_pip(args: argparse.Namespace) -> None: ensure_exists(args.name) if not args.pip_args: sys.exit("[!] Provide pip arguments, e.g. venvman pip myenv install requests") check_call([str(venv_pip(args.name)), *args.pip_args]) def cmd_freeze(args: argparse.Namespace) -> None: ensure_exists(args.name) check_call([str(venv_pip(args.name)), "freeze"]) def cmd_export(args: argparse.Namespace) -> None: ensure_exists(args.name) out = subprocess.check_output([str(venv_pip(args.name)), "freeze"], text=True) Path(args.output).write_text(out, encoding="utf-8") print(f"[+] Wrote {args.output}") def cmd_import(args: argparse.Namespace) -> None: ensure_exists(args.name) req = Path(args.requirements) if not req.exists(): sys.exit(f"[!] Requirements not found: {req}") check_call([str(venv_pip(args.name)), "install", "-r", str(req)]) # ---------- CLI wiring ---------- def build_parser() -> argparse.ArgumentParser: ap = argparse.ArgumentParser( prog="venvman", description="Manage Python virtual environments using venv" ) sub = ap.add_subparsers(dest="cmd", required=True) p = sub.add_parser("create", help="Create a new virtual environment") p.add_argument("name") p.add_argument("--python", help="Python interpreter to use (defaults to current)") p.set_defaults(func=cmd_create) p = sub.add_parser("list", help="List all environments") p.set_defaults(func=cmd_list) p = sub.add_parser("remove", help="Remove an environment") p.add_argument("name") p.set_defaults(func=cmd_remove) p = sub.add_parser("info", help="Show environment details") p.add_argument("name") p.set_defaults(func=cmd_info) p = sub.add_parser("path", help="Print the environment path") p.add_argument("name") p.set_defaults(func=cmd_path) p = sub.add_parser("run", help="Run a command inside the environment") p.add_argument("name") p.add_argument( "cmd", nargs=argparse.REMAINDER, help="Command to run (prefix with -- to separate)", ) p.set_defaults(func=cmd_run) p = sub.add_parser("pip", help="Run pip inside the environment") p.add_argument("name") p.add_argument("pip_args", nargs=argparse.REMAINDER) p.set_defaults(func=cmd_pip) p = sub.add_parser("freeze", help="pip freeze inside the environment") p.add_argument("name") p.set_defaults(func=cmd_freeze) p = sub.add_parser("export", help="Export requirements to a file") p.add_argument("name") p.add_argument("-o", "--output", required=True) p.set_defaults(func=cmd_export) p = sub.add_parser("import", help="Install from a requirements file") p.add_argument("name") p.add_argument("-r", "--requirements", required=True) p.set_defaults(func=cmd_import) return ap def main(argv: List[str] | None = None) -> None: parser = build_parser() args = parser.parse_args(argv) args.func(args) if __name__ == "__main__": main()

Example usage & outputs (abridged)

Output

 
OUTPUT 1 :

# 1) Create an environment
$ python venvman.py create demo
[*] Creating venv 'demo' with /usr/bin/python3 ...
[+] Created: /home/user/.venvs/demo
[i] Activate manually:
    source /home/user/.venvs/demo/bin/activate

# 2) List environments
$ python venvman.py list
demo  ->  /home/user/.venvs/demo/bin/python

# 3) Show detailed info
$ python venvman.py info demo
Name:        demo
Path:        /home/user/.venvs/demo
Executable:  /home/user/.venvs/demo/bin/python
Impl/Ver:    CPython 3.11.9 (main, ...)
Platform:    linux
Paths:
  data        /home/user/.venvs/demo
  include     /home/user/.venvs/demo/include
  platlib     /home/user/.venvs/demo/lib/python3.11/site-packages
  purelib     /home/user/.venvs/demo/lib/python3.11/site-packages
  ...
Site-packages:
  - /home/user/.venvs/demo/lib/python3.11/site-packages

# 4) Install packages inside that venv (pip passthrough)
$ python venvman.py pip demo install requests
Collecting requests ...
Successfully installed requests-2.32.3 ...

# 5) Run any command inside the venv (PATH is adjusted)
$ python venvman.py run demo -- python -V
Python 3.11.9

# 6) Freeze & export requirements
$ python venvman.py freeze demo
requests==2.32.3
$ python venvman.py export demo -o requirements.txt
[+] Wrote requirements.txt

# 7) Import requirements
$ python venvman.py import demo -r requirements.txt
Processing ./requirements.txt
Requirement already satisfied: requests==2.32.3 ...

# 8) Remove the env
$ python venvman.py remove demo
[*] Removing /home/user/.venvs/demo ...
[+] Removed.



What this tool does (detailed description)

  • Creates isolated virtual environments with python -m venv, defaulting to a tidy root ($VENV_HOME or ~/.venvs).
  • Lists environments by scanning that root and confirming a valid interpreter exists.
  • Removes environments safely by deleting the directory tree.
  • Shows info by asking the venv’s own Python to report version, implementation, config paths, and site-packages (this avoids guessing).
  • Runs commands inside the environment by prepending the venv’s bin/Scripts to PATH and exporting VIRTUAL_ENV.
  • Delegates to pip inside the venv for installs, upgrades, and queries.
  • Exports a deterministic requirements.txt via pip freeze, and imports it later.


Step-by-step explanation

  1. Config & constants
    • Detect a root folder for venvs (ROOT): $VENV_HOME or ~/.venvs.
    • Pick correct subfolder/executable names on Windows vs Unix (BIN_DIR, PY_NAME, PIP_NAME).
  2. Helper functions
    • venv_path(name) → where the env lives.
    • venv_python(name) / venv_pip(name) → paths to the venv’s Python/Pip.
    • ensure_exists(name) → exits early with a clear message if missing.
  3. create
    • Ensures ROOT exists; bails if the target already exists.
    • Calls [python, -m, venv, <path>] to create it.
    • Prints shell-specific activation hint.
  4. list
    • Scans ROOT, keeps entries that actually contain a Python interpreter.
    • Formats a neat 2-column list of <name> -> <interpreter path>.
  5. remove
    • Deletes the venv directory (shutil.rmtree), logging what happened.
  6. info
    • Runs the venv’s Python with a tiny inline script to emit a JSON blob describing:
      • version, implementation, executable, sys.prefix, sys.platform,
      • sysconfig.get_paths() (install/layout dirs),
      • site-packages paths (if available).
    • Prints those fields in a readable form.
  7. path
    • Prints the filesystem path to the venv (handy for scripting).
  8. run
    • Builds a modified environment: prepends <venv>/bin (or Scripts) to PATH and sets VIRTUAL_ENV.
    • Executes the command after -- using subprocess.call, returning the same exit code.
  9. pip
    • Runs the venv’s pip directly, forwarding all remaining args (install, uninstall, show, etc.).
  10. freeze/export/import
    • freeze runs pip freeze.
  • export writes pip freeze output to a file (-o).
  • import installs packages from a requirements file (-r).
  1. CLI wiring
  • Uses argparse subcommands.
  • Each subcommand sets func=cmd_*, and main() simply parses and dispatches to that function.

Cross-platform notes

  • Activation strings are different:
    • Linux/macOS: source <venv>/bin/activate
    • Windows (cmd/PowerShell): <venv>\Scripts\activate
  • Running commands uses PATH injection, so venvman run myenv -- python -V resolves to the venv’s Python.
  • The info command asks the venv’s own interpreter for details, which is robust across platforms and Python versions.