Python wrapper library for static PHP binaries with pre-built distribution support crazywhalecc/static-php-cli
Project description
static-php-py
Python wrapper library for static-php-cli, inspired by the static-php-cli project with pre-built binary distribution support.
Features
- Zero-configuration PHP execution: Install and run PHP scripts immediately
- Pre-built static binaries: No compilation required, binaries from static-php-cli 2.7.10
- Platform-specific wheels: Automatic platform detection via pip
- Flexible installation: Choose between API-only or bundled binary
- Remote binary support: Download and cache PHP binaries from custom URLs
- Type-safe API: Full type hints for better IDE support
Installation
Light (API only)
pip install static-php-py
Requires PHP available in system PATH or explicit binary path.
Installation
pip install static-php-py
Pip automatically selects the appropriate wheel for your platform. Platform-specific wheels include pre-built PHP binaries.
Includes pre-built PHP 8.3 binary for your platform (Linux x86_64/aarch64, macOS x86_64/arm64, Windows x64).
Development
# Clone repository
git clone https://github.com/samhsu-dev/static-php-py.git
cd static-php-py
# Create virtual environment with uv
uv venv
source .venv/bin/activate # or `.venv\Scripts\activate` on Windows
# Install with dev dependencies (includes Jupyter for demo notebook)
uv pip install -e ".[dev]"
# Register Jupyter kernel (optional, for running demo.ipynb)
python -m ipykernel install --user --name=static-php-py --display-name="static-php-py (.venv)"
Quick Start
Basic Usage
from static_php_py import PHP
# Use built-in PHP binary (from platform-specific wheel)
php = PHP.builtin()
# Or use local PHP binary
php = PHP.local("/usr/bin/php")
# Or download from remote URL
php = PHP.remote("https://example.com/php-8.4.zip")
# Execute PHP script
result = php.run("script.php")
if result.success:
print(result.stdout)
else:
print(f"Error: {result.stderr}")
# Evaluate PHP code
result = php.eval("echo 'Hello from PHP!';")
print(result.stdout) # Hello from PHP!
# Get PHP version
print(php.version()) # 8.4.0
# Get PHP binary path
print(php.path()) # /path/to/php
Usage
Load Local PHP Binary
from static_php_py import PHP
# Use local PHP binary with string path
php = PHP.local("/usr/local/bin/php")
result = php.run("script.php")
# Or use Path object
from pathlib import Path
php = PHP.local(Path("/usr/local/bin/php"))
Download Remote PHP Binary
from static_php_py import PHP
# Download binary directly
php = PHP.remote("https://example.com/php-8.4-cli")
# Download and extract archive (tar.gz, tgz, or zip)
php = PHP.remote("https://example.com/php-8.4.tar.gz")
php = PHP.remote("https://example.com/php-8.4.zip")
# Force re-download (ignore cache)
php = PHP.remote("https://example.com/php.tar.gz", force=True)
# Custom timeout (default: 300 seconds)
php = PHP.remote("https://example.com/php.tar.gz", timeout=600.0)
Execute PHP Scripts
from static_php_py import PHP
php = PHP.builtin()
# Run script with arguments
result = php.run("script.php", args=["--verbose", "--debug"])
# Run with timeout
result = php.run("long_script.php", timeout=30.0)
# Check result
if result.success:
print(f"Output: {result.stdout}")
else:
print(f"Error (code {result.return_code}): {result.stderr}")
Evaluate PHP Code
from static_php_py import PHP
php = PHP.builtin()
# Evaluate PHP code string
result = php.eval("echo 2 + 2;") # Output: 4
print(result.stdout)
# With timeout
result = php.eval("sleep(5); echo 'Done';", timeout=10.0)
Exception Handling
from static_php_py import PHP
from static_php_py.exceptions import (
BinaryNotFoundError,
DownloadError,
ExecutionError,
InvalidArchiveError,
)
# Handle binary not found
try:
php = PHP.builtin()
except BinaryNotFoundError:
print("PHP binary not found. Install platform-specific wheel or use PHP.local(path).")
# Handle download errors
try:
php = PHP.remote("https://example.com/php.zip")
except DownloadError as e:
print(f"Download failed: {e}")
except InvalidArchiveError as e:
print(f"Invalid archive: {e}")
# Handle execution errors
try:
result = php.run("script.php")
except ExecutionError as e:
print(f"Execution failed: {e}")
API Reference
PHP Class
Static Methods
PHP.builtin() -> PHP
Load built-in PHP binary from package resources.
Returns: PHP instance
Raises: BinaryNotFoundError if built-in binary not found (not installed via platform-specific wheel)
PHP.local(path: Path | str) -> PHP
Load PHP binary from local file system path.
Parameters:
path: Path to PHP binary (required, string or Path object)
Returns: PHP instance
Raises: BinaryNotFoundError if binary not found at specified path
PHP.remote(url: str, force: bool = False, timeout: float = 300.0) -> PHP
Download PHP binary from remote URL and return PHP instance.
Parameters:
url: Remote URL to PHP binary or archive (tar.gz, tgz, or zip)force: Force re-download ignoring cache (default: False)timeout: Download timeout in seconds (default: 300.0)
Returns: PHP instance
Raises: DownloadError on network failure, InvalidArchiveError on archive error
Instance Methods
run(script: Path | str, args: list[str] | None = None, timeout: float | None = None) -> ExecutionResulteval(code: str, timeout: float | None = None) -> ExecutionResultversion() -> strpath() -> Path
ExecutionResult
Result of PHP script execution.
Properties:
success: bool- True if exit code is 0return_code: int- Process exit codestdout: str- Standard outputstderr: str- Standard error
Exceptions
PHPError- Base exception for all static-php-py errorsBinaryNotFoundError- PHP binary not foundExecutionError- PHP execution failureDownloadError- Network/download failureInvalidArchiveError- Invalid tar.gz archive
Project Structure
static-php-py/
├── static_php_py/ # Main package
│ ├── __init__.py # Public API exports
│ ├── exceptions.py # Exception classes
│ ├── php.py # PHP class (includes create, download, cache_dir)
│ ├── models.py # ExecutionResult model
│ └── providers.py # Internal providers
├── resources/ # Resources package (PHP binaries)
│ ├── __init__.py
│ └── pyproject.toml
├── scripts/ # Build scripts
│ └── build_binaries.py # Binary wheel builder
├── tests/ # Test suite
│ ├── test_exceptions.py
│ ├── test_factory.py
│ ├── test_integration.py
│ ├── test_models.py
│ ├── test_php.py
│ └── test_providers.py
├── docs/ # Documentation
│ ├── idea.md # Architecture concepts
│ ├── design.md # Detailed design specification
│ └── todo.md # Implementation tasks
├── pyproject.toml # Project configuration
└── README.md # This file
Development
Run Tests
pytest tests/ -v
Code Quality
# Linting
ruff check static_php_py/
# Formatting
ruff format static_php_py/ tests/
# Type checking
mypy static_php_py/
Interactive Demo
# Open the demo notebook
jupyter notebook docs/demo.ipynb
# or
jupyter lab docs/demo.ipynb
The demo notebook (docs/demo.ipynb) demonstrates all public APIs with interactive examples.
Troubleshooting
PHP Binary Not Found
If you get BinaryNotFoundError:
-
Ensure platform-specific wheel is installed:
pip install --force-reinstall static-php-py
-
Or specify explicit path:
php = PHP.create(path="/usr/bin/php")
-
Or ensure PHP is in system PATH:
which php # Check if PHP is available
Download Failures
If download() fails:
- Check network connectivity
- Verify URL is accessible
- Try with
force=Trueto bypass cache - Increase
timeoutfor slow connections
Archive Extraction Errors
If InvalidArchiveError is raised:
- Verify URL points to valid tar.gz file
- Check archive contains
phpexecutable - Ensure archive is not corrupted
Architecture
For detailed architecture and design information, see:
- Architecture Concepts
- Design Specification
- API Demo Notebook - Interactive examples of all APIs
Publishing
For information on publishing to PyPI, see:
- Publishing Guide - Instructions for publishing to Test PyPI and production PyPI
Status
✅ Phase 1-8: Complete
⏳ Phase 9: CI/CD and Publishing (in progress)
License
Apache License 2.0 - See LICENSE file for details.
Acknowledgments
- static-php-cli - Inspiration and pre-built PHP binaries source
- Project maintained by samhsu-dev
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file static_php_py-0.1.0-py3-none-win_amd64.whl.
File metadata
- Download URL: static_php_py-0.1.0-py3-none-win_amd64.whl
- Upload date:
- Size: 5.1 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa5671e6ec6893e83fd9609726c54099b8fdca48ef0570f148e322baac74fe23
|
|
| MD5 |
90a1ecca094075037fdee10f68f1078e
|
|
| BLAKE2b-256 |
fd45cdbdb3938053ee1d49b236d71aca330fb450fcc2ac0d62bb10f1fce05036
|
File details
Details for the file static_php_py-0.1.0-py3-none-manylinux_2_17_x86_64.whl.
File metadata
- Download URL: static_php_py-0.1.0-py3-none-manylinux_2_17_x86_64.whl
- Upload date:
- Size: 4.9 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d84b8cf3d1f985e24d97bc12b93839ba9f552f933b88e782b7f78255cf60e438
|
|
| MD5 |
854a6b258538dbfbb0d87e78b53e9495
|
|
| BLAKE2b-256 |
4d55a6c414728e9e681d9e6b74c7db75cc1e7c9d66222d7fc94334c4648293e6
|
File details
Details for the file static_php_py-0.1.0-py3-none-manylinux_2_17_aarch64.whl.
File metadata
- Download URL: static_php_py-0.1.0-py3-none-manylinux_2_17_aarch64.whl
- Upload date:
- Size: 5.0 MB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
242158f93e52dd9f716ec8cbd4d09d5a5637784cc3c5f173b6708d51f80d11c8
|
|
| MD5 |
26b0862477079f095a2cf833ccee8ab9
|
|
| BLAKE2b-256 |
fb84abba3df6e07707671b9776142a24324b681801be9b08e5700cf1f6163cb1
|
File details
Details for the file static_php_py-0.1.0-py3-none-macosx_11_0_x86_64.whl.
File metadata
- Download URL: static_php_py-0.1.0-py3-none-macosx_11_0_x86_64.whl
- Upload date:
- Size: 4.8 MB
- Tags: Python 3, macOS 11.0+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
090586eb3ee36ea2df73bb26c8d3456c8c025f48a6946ff455acd22a1dc4ffd5
|
|
| MD5 |
a68bfd1ac27c4f6d54e5e4896f976b80
|
|
| BLAKE2b-256 |
3532d748315feb8ae0a50bf80a4a8a43e7202e744cf0b2c7d6efd5dc20b63643
|
File details
Details for the file static_php_py-0.1.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: static_php_py-0.1.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 4.7 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c4110c83bfcc29e591ffcac78b4d8fcabb1fadd4b6d76c7156614aa41eb4acf
|
|
| MD5 |
d264cbd55a81068773ad5b1a85c37669
|
|
| BLAKE2b-256 |
986ef2cdc2b011e16c9cadf9976544f86b37c501e55463eab44cb73d8a527c49
|
File details
Details for the file static_php_py-0.1.0-py3-none-any.whl.
File metadata
- Download URL: static_php_py-0.1.0-py3-none-any.whl
- Upload date:
- Size: 26.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b2601b5cbc3051f24eb69766a1a0b6042d919758afb4a30bb345867ca019076
|
|
| MD5 |
edf438d69436736e894975b8ac0343e1
|
|
| BLAKE2b-256 |
30a6c0d896f46668eab321a5b300d1878868ae9a382f360d283e0f2b5000fcab
|