Hands-on workshop
Protect Python Applications
A hands-on lab for Python code obfuscation, runtime protection, packaging, and deployment.
PyArmor 9.2.7 · Python 3.12 · FastAPI · Docker · 13 chapters · ~3 h
$ uv run pyarmor gen -O build/protected -r --exclude app/frontend app
INFO obfuscate scripts OK
$ head -n 2 build/protected/app/backend/business_logic/scoring.py
# Pyarmor 9.2.7 (trial), 000000, non-profits, 2026-10-08T09:17:16.748765
from pyarmor_runtime_000000 import __pyarmor__
$ uv run python scripts/verify.py --tests
✓ every module is obfuscated and present
✓ no function names, constant names or long strings found as plain text
38 passed in 0.12s
✓ the protected build passes the same tests as the originalWhat you will see
Real output from the workshop runs.
05 · Obfuscation
Readable source → three-line stub
WEIGHTS = {"value": 0.55, "engagement": 0.45, "risk_penalty": 0.30}
def classify(score: float) -> str:
"""Name the band a business score falls in."""
for threshold, label in CLASS_THRESHOLDS:
if score >= threshold:
return label
return "watch"# Pyarmor 9.2.7 (trial), 000000, non-profits, 2026-10-08T09:17:16.748765 from pyarmor_runtime_000000 import __pyarmor__ __pyarmor__(__name__, __file__, b'PY000000\x00\x03\x0c\x00\xcb\r\r\n\x80\x00\x01\x00\x08...
Verify
Same behaviour
38 / 38
tests pass on the original and the protected build.
06 · Runtime
No runtime, no app
ModuleNotFoundError: No module named 'pyarmor_runtime_000000'
09 · Docker
No source in the image
$ ls /src ls: cannot access '/src': No such file or directory $ id uid=10001(app) gid=10001(app) groups=10001(app)
06 · Expiry
Builds that stop working
RuntimeError: this license key is expired (1:11086)
07 · Limits
Still visible at runtime
constant WEIGHTS = {'value': 0.55, 'engagement': 0.45, 'risk_penalty': 0.3}Threat model
Security model →| Scenario | Attacker has | Obfuscation |
|---|---|---|
| ASource available | Repository or plain .py files | Nothing protected |
| BProtected artifact | Obfuscated app + runtime | Reading and reuse get much harder |
| CEnvironment controlled | Shell, files, memory, env vars | Not the boundary: protect the host |
Chapters
~3 hours- 00IntroductionCode protection, obfuscation and the threat model10m
- 01Project SetupClone, install with uv, run the baseline tests10m
- 02Explore SourceRead the app and find the logic worth protecting10m
- 03Baseline AppCall every endpoint and record the answers10m
- 04PyArmor SetupVersion, CLI, trial limits and licensing5m
- 05ObfuscationProtect a script, then the package, and verify it15m
- 06RuntimeBreak it three ways, add an expiry date15m
- 07Original vs ProtectedWhat changed, what did not, and why it works15m
- 08PackagingArchives and PyInstaller bundles15m
- 09DockerA two-stage image with no source, inspected20m
- 10DeploymentReverse proxy, HTTPS, health checks, logs15m
- 11Security RealityWhat obfuscation protects, and what it cannot15m
- 12Best PracticesThe production checklist15m
Run it locally
Site + live Lab on :3300, protected API on :8300. No account, no keys.
git clone https://github.com/jars-demo/pyarmor-demo.git
cd pyarmor-demo
docker compose up -d --build