Project Setup

1. The Cross-Platform Venv Resolution Problem

Standard python -m venv generates OS-specific activation scripts that modify PATH and VIRTUAL_ENV. When a CLI entry point executes outside an activated shell, it often resolves to the system interpreter. This breaks dependency resolution and triggers silent ModuleNotFoundError exceptions. Strict isolation, as foundational to Project Setup & Dependency Management, prevents interpreter drift before addressing OS-specific path quirks.

1. The Cross-Platform Venv Resolution Problem

Standard python -m venv generates OS-specific activation scripts that modify PATH and VIRTUAL_ENV. When a CLI entry point executes outside an activated shell, it often resolves to the system interpreter. This breaks dependency resolution and triggers silent ModuleNotFoundError exceptions. Strict isolation, as foundational to Project Setup & Dependency Management, prevents interpreter drift before addressing OS-specific path quirks.

2. Diagnosing sys.executable and PATH Divergence

Run this diagnostic to identify interpreter fallback across environments:

python -c "import sys, os; print(f'Executable: {sys.executable}\nPATH: {os.environ.get(\"PATH\")}')"

Compare outputs inside and outside the activated environment. On Windows, use where python; on POSIX, use which python. If the executable points to a global Python installation, your CLI will fail to locate environment-scoped packages.

Debugging Flow:

  1. Execute the diagnostic inside the activated .venv.
  2. Run it again in a fresh terminal without activation.
  3. Compare sys.executable paths to confirm fallback behavior.

Edge Cases:

  • Conda environments prepend their own bin/Scripts directories, overriding system PATH.
  • Windows App Execution Aliases (python.exe in %LOCALAPPDATA%\Microsoft\WindowsApps) intercept unqualified python calls.

3. Cross-Platform Venv Creation & Activation Strategy

Use explicit activation commands to guarantee consistent environment state across shells:

# POSIX (bash/zsh)
python3 -m venv .venv && source .venv/bin/activate

# Windows PowerShell
python -m venv .venv && .venv\Scripts\Activate.ps1

Define entry points in pyproject.toml to generate platform-aware wrapper executables:

[project.scripts]
mycli = "mycli.main:cli"

These wrappers auto-resolve the correct interpreter. For deeper isolation patterns and dependency pinning strategies, consult Virtual Environments & Isolation Best Practices.

Debugging Flow:

  1. Verify .venv creation succeeds on both OS targets.
  2. Confirm activation sets VIRTUAL_ENV and prepends the correct bin/Scripts to PATH.
  3. Test mycli --help without prior manual activation.

Edge Cases:

  • PowerShell ExecutionPolicy blocks Activate.ps1. Run Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser to resolve.
  • Windows lacks a native python3 alias. Use python or create a shim.

4. Fixing Entry-Point Shebang & Wrapper Failures

pip install -e . generates wrappers in .venv/bin/ (POSIX) or .venv/Scripts/ (Windows). Inspect the generated headers to verify interpreter paths:

# POSIX
head -n 1 .venv/bin/mycli

# Windows (binary wrapper inspection)
powershell -Command "Get-Content .venv\Scripts\mycli.exe -Encoding byte | Select-Object -First 20"

Mismatches occur when #!/usr/bin/env python3 is hardcoded but the environment uses a different path. Use a deterministic launcher pattern to force correct resolution:

# src/mycli/__main__.py
import sys
import os

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from mycli.main import cli

if __name__ == "__main__":
 cli()

Debugging Flow:

  1. Inspect the generated wrapper shebang/header.
  2. Trace execution with python -v -m mycli.
  3. Apply the sys.path override if the wrapper fails to locate modules.

Edge Cases:

  • Windows paths exceeding 260 characters truncate during wrapper generation. Enable long paths via registry or use shorter virtual environment paths.
  • Spaces in venv paths cause POSIX shebang truncation. Always use underscore-separated paths (e.g., .venv_cli).

5. Production-Ready Distribution & CI Validation

Validate cross-platform compatibility using a GitHub Actions matrix. This ensures deterministic builds and catches OS-specific wrapper corruption early.

name: Cross-Platform Venv Test
on: [push]
jobs:
 test:
 runs-on: ${{ matrix.os }}
 strategy:
 matrix:
 os: [ubuntu-latest, windows-latest, macos-latest]
 steps:
 - uses: actions/checkout@v4
 - name: Setup venv
 run: python -m venv .venv
 - name: Install CLI
 run: |
 if [ "$RUNNER_OS" == "Windows" ]; then
 .venv\Scripts\pip install -e .
 .venv\Scripts\mycli --version
 else
 .venv/bin/pip install -e .
 .venv/bin/mycli --version
 fi
 shell: bash

Debugging Flow:

  1. Execute the matrix pipeline.
  2. Isolate OS-specific failure logs from the runner output.
  3. Validate wrapper binary execution directly in the CI environment.

Edge Cases:

  • GitHub Actions caching (actions/cache) can interfere with fresh .venv creation. Disable caching for the .venv directory during initial validation.
  • Line-ending corruption (CRLF vs LF) in POSIX wrappers breaks execution. Configure .gitattributes with * text=auto eol=lf to enforce consistent line endings.