{"id":906,"date":"2025-12-12T21:01:45","date_gmt":"2025-12-13T02:01:45","guid":{"rendered":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/?p=906"},"modified":"2025-12-17T00:47:26","modified_gmt":"2025-12-17T05:47:26","slug":"python-runner-web-template","status":"publish","type":"post","link":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/python-runner-web-template\/","title":{"rendered":"Python Runner Web Template"},"content":{"rendered":"<body>\n<h4 class=\"wp-block-heading\">Python Runner Web Template: Build Self-Hosted Python Tools on Your Website (No SaaS Required)<\/h4>\n\n\n\n<p><strong>Meta Description (Yoast \/ RankMath):<\/strong><br>Deploy Python tools directly on your website with Python Runner Web Template. Run scripts, generate PDFs, automate workflows, and stay fully self-hosted.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Introduction: Python Tools Belong on <em>Your<\/em> Website<\/h2>\n\n\n\n<p>Most online tools today force creators into a difficult tradeoff:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Convenience <strong>vs<\/strong> ownership<\/li>\n\n\n\n<li>Speed <strong>vs<\/strong> control<\/li>\n\n\n\n<li>Cloud access <strong>vs<\/strong> long-term reliability<\/li>\n<\/ul>\n\n\n\n<p>The <strong>Python Runner Web Template<\/strong> was built to end that tradeoff.<\/p>\n\n\n\n<p>This template allows you to deploy <strong>real Python-powered tools directly on your website<\/strong>, without depending on third-party SaaS platforms, expiring dashboards, or external APIs you don\u2019t control.<\/p>\n\n\n\n<p>If you\u2019ve ever wanted to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>run Python scripts from a browser<\/li>\n\n\n\n<li>generate PDFs or reports for users<\/li>\n\n\n\n<li>build internal tools or paid utilities<\/li>\n\n\n\n<li>host AI-assisted workflows on your own domain<\/li>\n<\/ul>\n\n\n\n<p>\u2026this template was built specifically for that purpose.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83c\udf10 What Is the Python Runner Web Template?<\/h2>\n\n\n\n<p>The Python Runner Web Template is a <strong>ready-to-deploy web interface<\/strong> that connects frontend UI elements (buttons, forms, inputs) to backend Python scripts running on your server.<\/p>\n\n\n\n<p>In short:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>It turns Python scripts into web tools.<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p>No frameworks required.<br>No SaaS dependency.<br>No forced subscriptions.<\/p>\n\n\n\n<p>You upload it to your hosting, connect scripts, and it works.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"\ud83d\udda5\ufe0f How the Python Runner Web Template Works, \ud83c\udf10 What Is the Python Runner Web Template?\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/uIVU18aCjGw?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\u2699\ufe0f Core Features<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ud83c\udf10 Browser-based Python execution<\/li>\n\n\n\n<li>\ud83e\udde9 Modular script architecture<\/li>\n\n\n\n<li>\ud83d\udcc4 PDF &amp; HTML generation via web UI<\/li>\n\n\n\n<li>\ud83d\udda5\ufe0f Works on shared hosting (cPanel-friendly)<\/li>\n\n\n\n<li>\ud83d\udd10 No exposed API keys<\/li>\n\n\n\n<li>\ud83d\udcc2 Clean separation of frontend and scripts<\/li>\n\n\n\n<li>\ud83e\udde0 AI-ready (bring your own logic)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\udde0 Why the Web Template Was Built<\/h2>\n\n\n\n<p>After building <strong>Python Runner (Local)<\/strong>, one thing became clear:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>People wanted the same power \u2014 but accessible through a website.<\/p>\n<\/blockquote>\n\n\n\n<p>However, existing solutions had major problems:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>cloud lock-in<\/li>\n\n\n\n<li>usage limits<\/li>\n\n\n\n<li>forced subscriptions<\/li>\n\n\n\n<li>complex DevOps stacks<\/li>\n<\/ul>\n\n\n\n<p>The Python Runner Web Template was built to solve this with:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>simple PHP + Python integration<\/strong><\/li>\n\n\n\n<li><strong>zero vendor lock-in<\/strong><\/li>\n\n\n\n<li><strong>full control over execution and outputs<\/strong><\/li>\n<\/ul>\n\n\n\n<p>It\u2019s ideal for creators who want to <strong>sell tools<\/strong>, not just scripts.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udda5\ufe0f How the Python Runner Web Template Works<\/h2>\n\n\n\n<p>At a high level:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>User visits a web page<\/li>\n\n\n\n<li>User clicks a button or submits a form<\/li>\n\n\n\n<li>The template triggers a Python script on the server<\/li>\n\n\n\n<li>Python generates output (PDF, HTML, text, data)<\/li>\n\n\n\n<li>The result is returned to the browser or saved<\/li>\n<\/ol>\n\n\n\n<p>This allows you to create:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>report generators<\/li>\n\n\n\n<li>document builders<\/li>\n\n\n\n<li>calculators<\/li>\n\n\n\n<li>AI-powered analysis tools<\/li>\n\n\n\n<li>internal dashboards<\/li>\n<\/ul>\n\n\n\n<p>All hosted on <strong>your own domain<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udcc2 Web Template Folder Structure<\/h2>\n\n\n\n<p>The template uses a clean, scalable layout:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python-runner-web\/\n\u2502\n\u251c\u2500\u2500 index.html\n\u251c\u2500\u2500 run.php\n\u251c\u2500\u2500 scripts\/\n\u2502   \u251c\u2500\u2500 generate_pdf.py\n\u2502   \u251c\u2500\u2500 analyze_data.py\n\u2502   \u2514\u2500\u2500 ai_report.py\n\u2502\n\u251c\u2500\u2500 output\/\n\u2502   \u251c\u2500\u2500 pdf\/\n\u2502   \u251c\u2500\u2500 html\/\n\u2502   \u2514\u2500\u2500 logs\/\n\u2502\n\u2514\u2500\u2500 assets\/\n    \u251c\u2500\u2500 css\/\n    \u2514\u2500\u2500 js\/\n<\/code><\/pre>\n\n\n\n<p>This structure makes it easy to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>add new tools<\/li>\n\n\n\n<li>reuse scripts<\/li>\n\n\n\n<li>expand into full apps<\/li>\n\n\n\n<li>integrate with member systems<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\udde9 Web Installation (cPanel \/ Hosting)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Requirements<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>cPanel or similar hosting<\/li>\n\n\n\n<li>Python enabled (most hosts support it)<\/li>\n\n\n\n<li>PHP (standard on cPanel)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Installation Steps<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Upload the ZIP file to your web directory<br>Example: <code>public_html\/python-runner-web\/<\/code><\/li>\n\n\n\n<li>Unzip via File Manager<\/li>\n\n\n\n<li>Set folder permissions: <code>scripts\/ \u2192 755 output\/ \u2192 755<\/code><\/li>\n\n\n\n<li>Open in browser: <code>https:\/\/yourdomain.com\/python-runner-web\/<\/code><\/li>\n<\/ol>\n\n\n\n<p>No database required.<br>No cron jobs required.<br>No special server configuration needed.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udcc4 Generating PDFs, HTML &amp; User Downloads<\/h2>\n\n\n\n<p>One of the strongest use cases of the web template is <strong>on-demand document generation<\/strong>.<\/p>\n\n\n\n<p>You can build tools that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>generate PDFs instantly<\/li>\n\n\n\n<li>export HTML reports<\/li>\n\n\n\n<li>create structured documents<\/li>\n\n\n\n<li>save files per user request<\/li>\n<\/ul>\n\n\n\n<p>Examples:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>credit repair letters<\/li>\n\n\n\n<li>legal notices<\/li>\n\n\n\n<li>sales summaries<\/li>\n\n\n\n<li>AI-generated documents<\/li>\n\n\n\n<li>educational worksheets<\/li>\n<\/ul>\n\n\n\n<p>Unlike cloud platforms, <strong>files never expire<\/strong> unless <em>you<\/em> choose to remove them.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\udd16 AI-Assisted Web Tools (Without API Exposure)<\/h2>\n\n\n\n<p>The Python Runner Web Template is <strong>AI-ready<\/strong>, meaning:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>You can integrate AI logic inside Python<\/li>\n\n\n\n<li>API keys stay server-side<\/li>\n\n\n\n<li>No client-side exposure<\/li>\n\n\n\n<li>No per-request SaaS fees<\/li>\n<\/ul>\n\n\n\n<p>This is ideal for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>AI summarization tools<\/li>\n\n\n\n<li>content generators<\/li>\n\n\n\n<li>data analysis<\/li>\n\n\n\n<li>custom automation<\/li>\n<\/ul>\n\n\n\n<p>You control:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>prompts<\/li>\n\n\n\n<li>models<\/li>\n\n\n\n<li>limits<\/li>\n\n\n\n<li>output format<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd12 Security &amp; Ownership Advantages<\/h2>\n\n\n\n<p>Cloud-based tools typically:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>log user behavior<\/li>\n\n\n\n<li>limit usage<\/li>\n\n\n\n<li>revoke access<\/li>\n\n\n\n<li>lock data behind accounts<\/li>\n<\/ul>\n\n\n\n<p>Python Runner Web Template does none of that.<\/p>\n\n\n\n<p>\u2714 Scripts live on <em>your<\/em> server<br>\u2714 Users interact with <em>your<\/em> UI<br>\u2714 Files remain accessible<br>\u2714 You decide how long data exists<\/p>\n\n\n\n<p>This makes it suitable for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>legal tools<\/li>\n\n\n\n<li>private business utilities<\/li>\n\n\n\n<li>internal dashboards<\/li>\n\n\n\n<li>paid member tools<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udc65 Who Should Use the Web Template?<\/h2>\n\n\n\n<p>This template is ideal for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Developers building web-based utilities<\/li>\n\n\n\n<li>Entrepreneurs selling downloadable tools<\/li>\n\n\n\n<li>Agencies creating client dashboards<\/li>\n\n\n\n<li>Educators hosting interactive tools<\/li>\n\n\n\n<li>Anyone tired of SaaS dependency<\/li>\n<\/ul>\n\n\n\n<p>If you already use <strong>Python Runner (Local)<\/strong>, the web template is the natural next step.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd01 Python Runner Local vs Web Template<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Feature<\/th><th>Local<\/th><th>Web Template<\/th><\/tr><\/thead><tbody><tr><td>Offline use<\/td><td>\u2705<\/td><td>\u274c<\/td><\/tr><tr><td>Browser-based<\/td><td>\u274c<\/td><td>\u2705<\/td><\/tr><tr><td>Self-hosted<\/td><td>\u2705<\/td><td>\u2705<\/td><\/tr><tr><td>Sell as tool<\/td><td>\u26a0\ufe0f<\/td><td>\u2705<\/td><\/tr><tr><td>User interaction<\/td><td>\u274c<\/td><td>\u2705<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Many users choose <strong>both<\/strong>, which is why the <strong>Python Runner Bundle<\/strong> exists.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd17 How It Fits the Studio1Live Ecosystem<\/h2>\n\n\n\n<p>The Python Runner Web Template powers tools like:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>JD Sales GEN<\/strong> (report automation)<\/li>\n\n\n\n<li><strong>AI Web Build Kit<\/strong> (site generators)<\/li>\n\n\n\n<li><strong>Credit Repair Tools<\/strong><\/li>\n\n\n\n<li><strong>Internal Admin Dashboards<\/strong><\/li>\n<\/ul>\n\n\n\n<p>It\u2019s not a one-off script \u2014 it\u2019s infrastructure.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udc49 Download Python Runner Web Template<\/h2>\n\n\n\n<p>If you want to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>run Python from the browser<\/li>\n\n\n\n<li>build sellable web tools<\/li>\n\n\n\n<li>stay fully self-hosted<\/li>\n\n\n\n<li>avoid SaaS lock-in<\/li>\n<\/ul>\n\n\n\n<p>This template was built for you.<\/p>\n\n\n\n<p>\ud83d\udd17 <strong>Download Python Runner Web Template:<\/strong><br>\ud83d\udc49 <a href=\"https:\/\/fixyourowncredit.studio1live.com\/downloads\/downloads\/python-runner-web-template\/\">https:\/\/fixyourowncredit.studio1live.com\/downloads\/downloads\/python-runner-web-template\/<\/a><\/p>\n\n\n\n<p>\ud83d\udd17 <strong>View All Studio1Live Templates:<\/strong><br>\ud83d\udc49 <a href=\"https:\/\/studio1live.com\/templates\/\">https:\/\/studio1live.com\/templates\/<\/a><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Final Thought<\/h2>\n\n\n\n<p>The Python Runner Web Template gives you something most platforms don\u2019t:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Freedom to build tools that last.<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p>No subscriptions.<br>No platform risk.<br>Just tools that work \u2014 on <em>your<\/em> site.<\/p>\n\n\n\n<p>How to build this on your own. You can purchase it and resell if you like. Follows the code instructions below. <\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Option 1) Flask app via cPanel \u201cSetup Python App\u201d (clean + safe)<\/h5>\n\n\n\n<h3 class=\"wp-block-heading\">Folder layout<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/&lt;USER&gt;\/python\/py_build\/\n  app.py\n  requirements.txt\n  scripts\/            \u2190 uploaded .py files will live here\n  uploads\/            \u2190 temp upload area (auto-created)\n\/home\/&lt;USER&gt;\/python\/py_build\/venv\/   \u2190 created by cPanel or you\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><code>requirements.txt<\/code><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Flask==3.0.0\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><code>app.py<\/code> (single file, ready to paste)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>import os, re, subprocess, shlex, time\nfrom pathlib import Path\nfrom flask import Flask, request, redirect, url_for, render_template_string, flash, send_from_directory\n\n# --- CONFIG ---\nBASE_DIR = Path(__file__).resolve().parent\nSCRIPTS_DIR = BASE_DIR \/ \"scripts\"\nUPLOADS_DIR = BASE_DIR \/ \"uploads\"\nPYTHON_BIN = os.environ.get(\"PY_BUILD_PYTHON\", sys.executable) if 'sys' in globals() else \"python3\"\nTIMEOUT_SECONDS = 20\nMAX_OUTPUT_BYTES = 200_000  # ~200 KB\n\nSCRIPTS_DIR.mkdir(exist_ok=True)\nUPLOADS_DIR.mkdir(exist_ok=True)\n\nALLOWED = re.compile(r\"^[A-Za-z0-9_\\-\\.]+\\.py$\")  # only .py, no subpaths\n\napp = Flask(__name__)\napp.secret_key = os.environ.get(\"PY_BUILD_SECRET\", \"change-me-please\")\n\nHTML = \"\"\"\n&lt;!doctype html&gt;\n&lt;title&gt;Studio1Live \u2014 Python Builder&lt;\/title&gt;\n&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"&gt;\n&lt;style&gt;\n body{font-family:system-ui,Segoe UI,Arial,sans-serif;padding:20px;max-width:900px;margin:auto;}\n h1{font-size:1.4rem;margin:0 0 12px}\n .row{display:flex;gap:16px;flex-wrap:wrap}\n form, .card{border:1px solid #ddd;border-radius:12px;padding:16px}\n .list{flex:1 1 420px}\n .runout{white-space:pre-wrap;background:#111;color:#eee;padding:12px;border-radius:12px;overflow:auto;max-height:400px}\n button{cursor:pointer;border:1px solid #333;border-radius:10px;padding:8px 14px;background:#111;color:#fff}\n input[type=file]{display:block;margin:8px 0}\n .muted{color:#666}\n .name{font-weight:600}\n .actions{display:flex;gap:8px}\n&lt;\/style&gt;\n&lt;h1&gt;Studio1Live \u2014 Python Runner&lt;\/h1&gt;\n\n&lt;div class=\"row\"&gt;\n  &lt;form method=\"post\" enctype=\"multipart\/form-data\" action=\"{{ url_for('upload') }}\"&gt;\n    &lt;div&gt;&lt;b&gt;Upload a .py file&lt;\/b&gt;&lt;\/div&gt;\n    &lt;input type=\"file\" name=\"file\" accept=\".py\" required&gt;\n    &lt;button&gt;Upload&lt;\/button&gt;\n    &lt;div class=\"muted\"&gt;Files are stored in &lt;code&gt;scripts\/&lt;\/code&gt;. Only .py allowed.&lt;\/div&gt;\n  &lt;\/form&gt;\n\n  &lt;div class=\"list\"&gt;\n    &lt;div class=\"card\"&gt;\n      &lt;b&gt;Available scripts&lt;\/b&gt;\n      &lt;ul&gt;\n      {% for f in files %}\n        &lt;li&gt;\n          &lt;span class=\"name\"&gt;{{ f }}&lt;\/span&gt;\n          &lt;div class=\"actions\"&gt;\n            &lt;form method=\"post\" action=\"{{ url_for('run_script') }}\" style=\"display:inline\"&gt;\n              &lt;input type=\"hidden\" name=\"filename\" value=\"{{ f }}\"&gt;\n              &lt;button&gt;Run&lt;\/button&gt;\n            &lt;\/form&gt;\n            &lt;a href=\"{{ url_for('download_script', filename=f) }}\"&gt;Download&lt;\/a&gt;\n          &lt;\/div&gt;\n        &lt;\/li&gt;\n      {% else %}\n        &lt;li class=\"muted\"&gt;No scripts yet. Upload above.&lt;\/li&gt;\n      {% endfor %}\n      &lt;\/ul&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/div&gt;\n\n{% with messages = get_flashed_messages() %}\n  {% if messages %}\n    &lt;div class=\"card\" style=\"margin-top:16px\"&gt;\n      {% for m in messages %}\n        &lt;div&gt;{{ m|safe }}&lt;\/div&gt;\n      {% endfor %}\n    &lt;\/div&gt;\n  {% endif %}\n{% endwith %}\n\n{% if output %}\n  &lt;div class=\"card\" style=\"margin-top:16px\"&gt;\n    &lt;b&gt;Output \u2014 {{ filename }}&lt;\/b&gt;\n    &lt;div class=\"runout\"&gt;{{ output }}&lt;\/div&gt;\n  &lt;\/div&gt;\n{% endif %}\n\"\"\"\n\ndef list_scripts():\n    return sorted([p.name for p in SCRIPTS_DIR.glob(\"*.py\") if ALLOWED.match(p.name)])\n\n@app.route(\"\/\", methods=[\"GET\"])\ndef home():\n    return render_template_string(HTML, files=list_scripts(), output=None, filename=None)\n\n@app.route(\"\/upload\", methods=[\"POST\"])\ndef upload():\n    file = request.files.get(\"file\")\n    if not file or not file.filename:\n        flash(\"No file provided.\")\n        return redirect(url_for('home'))\n    name = os.path.basename(file.filename)\n    if not ALLOWED.match(name):\n        flash(\"Invalid filename. Only .py allowed.\")\n        return redirect(url_for('home'))\n    temp = UPLOADS_DIR \/ name\n    file.save(temp)\n    dest = SCRIPTS_DIR \/ name\n    temp.replace(dest)\n    flash(f\"Uploaded &lt;b&gt;{name}&lt;\/b&gt; to scripts.\")\n    return redirect(url_for('home'))\n\n@app.route(\"\/download\/&lt;path:filename&gt;\")\ndef download_script(filename):\n    if not ALLOWED.match(filename):\n        return \"Invalid filename\", 400\n    return send_from_directory(SCRIPTS_DIR, filename, as_attachment=True)\n\n@app.route(\"\/run\", methods=[\"POST\"])\ndef run_script():\n    filename = request.form.get(\"filename\",\"\")\n    if not ALLOWED.match(filename):\n        flash(\"Invalid filename.\")\n        return redirect(url_for('home'))\n    script_path = SCRIPTS_DIR \/ filename\n    if not script_path.exists():\n        flash(\"File not found.\")\n        return redirect(url_for('home'))\n\n    # Run safely with timeout; no args; isolated cwd\n    try:\n        cmd = [PYTHON_BIN, str(script_path.name)]\n        result = subprocess.run(\n            cmd,\n            cwd=SCRIPTS_DIR,\n            capture_output=True,\n            text=True,\n            timeout=TIMEOUT_SECONDS\n        )\n        out = (result.stdout or \"\") + (\"\\n\" + result.stderr if result.stderr else \"\")\n        if len(out.encode(\"utf-8\")) &gt; MAX_OUTPUT_BYTES:\n            out = out[:MAX_OUTPUT_BYTES] + \"\\n...\\n[truncated]\"\n    except subprocess.TimeoutExpired:\n        out = f\"[Error] Timed out after {TIMEOUT_SECONDS}s.\"\n    except Exception as e:\n        out = f\"[Error] {e}\"\n\n    return render_template_string(HTML, files=list_scripts(), output=out, filename=filename)\n\n# cPanel WSGI entry point:\n# In \"Setup Python App\", set:\n#   Application startup file: app.py\n#   Application entry point: app\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">cPanel steps<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open <strong>Setup Python App<\/strong> \u2192 Create app (Python 3.9+), <strong>Application URL<\/strong>: <code>\/py_build<\/code> on <code>studio1live.com<\/code>.<\/li>\n\n\n\n<li>Point <strong>App Directory<\/strong> to <code>\/home\/&lt;USER&gt;\/python\/py_build<\/code>.<\/li>\n\n\n\n<li><strong>Startup file:<\/strong> <code>app.py<\/code> \u2014 <strong>Entry point:<\/strong> <code>app<\/code>.<\/li>\n\n\n\n<li>Click \u201cEnter to virtual environment\u201d \u2192 run: <code>pip install -r \/home\/&lt;USER&gt;\/python\/py_build\/requirements.txt<\/code><\/li>\n\n\n\n<li><strong>Restart<\/strong> the app.<\/li>\n\n\n\n<li>Visit: <code>https:\/\/studio1live.com\/py_build<\/code>\n<ul class=\"wp-block-list\">\n<li>Upload <code>.py<\/code> files<\/li>\n\n\n\n<li>Click <strong>Run<\/strong> next to any file<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\ud83d\udd12 Security notes: this allows executing uploaded Python in your account. Keep it private or protect with HTTP Auth. The app enforces a 20s timeout and only allows <code>.py<\/code> names (no paths).<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h4 class=\"wp-block-heading\">Option 2) One-file <strong>PHP<\/strong> page that calls Python (works on any cPanel)<\/h4>\n\n\n\n<p>If you don\u2019t have \u201cSetup Python App\u201d, use PHP to run Python.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Folder layout<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/&lt;USER&gt;\/public_html\/py_build\/\n  index.php\n  scripts\/          \u2190 uploaded .py live here\n  uploads\/          \u2190 temp\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">PHP page: <code>public_html\/py_build\/index.php<\/code><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\/\/ Simple Python runner (upload + list + run) via PHP.\n\/\/ Set your python binary (venv recommended):\n$PYTHON = '\/usr\/local\/bin\/python3'; \/\/ or '\/home\/&lt;USER&gt;\/python\/venv\/bin\/python'\n$BASE = __DIR__;\n$SCRIPTS = $BASE . '\/scripts';\n$UPLOADS = $BASE . '\/uploads';\n@mkdir($SCRIPTS, 0755, true);\n@mkdir($UPLOADS, 0755, true);\n\nfunction allowed($name) {\n  return preg_match('\/^[A-Za-z0-9_\\-\\.]+\\.py$\/', $name);\n}\n\n$msg = '';\n$out = '';\n$runFile = '';\n\nif ($_SERVER['REQUEST_METHOD']==='POST' &amp;&amp; isset($_FILES['file'])) {\n  if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {\n    $name = basename($_FILES['file']['name']);\n    if (!allowed($name)) {\n      $msg = \"Invalid filename.\";\n    } else {\n      $tmp = $UPLOADS . '\/' . $name;\n      move_uploaded_file($_FILES['file']['tmp_name'], $tmp);\n      rename($tmp, $SCRIPTS . '\/' . $name);\n      $msg = \"Uploaded &lt;b&gt;$name&lt;\/b&gt; to scripts.\";\n    }\n  } else {\n    $msg = \"Upload error.\";\n  }\n}\n\nif ($_SERVER['REQUEST_METHOD']==='POST' &amp;&amp; isset($_POST['run'])) {\n  $runFile = basename($_POST['run']);\n  if (allowed($runFile) &amp;&amp; file_exists($SCRIPTS . '\/' . $runFile)) {\n    $cmd = escapeshellcmd($PYTHON) . ' ' . escapeshellarg($runFile);\n    $descriptorspec = [\n      0 =&gt; [\"pipe\", \"r\"],\n      1 =&gt; [\"pipe\", \"w\"],\n      2 =&gt; [\"pipe\", \"w\"]\n    ];\n    $proc = proc_open($cmd, $descriptorspec, $pipes, $SCRIPTS);\n    if (is_resource($proc)) {\n      fclose($pipes[0]);\n      $stdout = stream_get_contents($pipes[1]); fclose($pipes[1]);\n      $stderr = stream_get_contents($pipes[2]); fclose($pipes[2]);\n      $code = proc_close($proc);\n      $out = $stdout . ($stderr ? \"\\n\".$stderr : '');\n      if (strlen($out) &gt; 200000) $out = substr($out, 0, 200000) . \"\\n...\\n[truncated]\";\n    } else {\n      $out = \"[Error] Could not execute.\";\n    }\n  } else {\n    $out = \"Invalid file.\";\n  }\n}\n\n$files = array_values(array_filter(scandir($SCRIPTS), function($f){\n  return allowed($f);\n}));\n?&gt;\n&lt;!doctype html&gt;\n&lt;html&gt;\n&lt;head&gt;\n&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"&gt;\n&lt;title&gt;Studio1Live \u2014 Python Runner&lt;\/title&gt;\n&lt;style&gt;\n body{font-family:system-ui,Segoe UI,Arial,sans-serif;padding:20px;max-width:900px;margin:auto;}\n h1{font-size:1.4rem;margin:0 0 12px}\n .row{display:flex;gap:16px;flex-wrap:wrap}\n form, .card{border:1px solid #ddd;border-radius:12px;padding:16px}\n .list{flex:1 1 420px}\n .runout{white-space:pre-wrap;background:#111;color:#eee;padding:12px;border-radius:12px;overflow:auto;max-height:400px}\n button{cursor:pointer;border:1px solid #333;border-radius:10px;padding:8px 14px;background:#111;color:#fff}\n input[type=file]{display:block;margin:8px 0}\n .muted{color:#666}\n .name{font-weight:600}\n .actions{display:flex;gap:8px}\n&lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n&lt;h1&gt;Studio1Live \u2014 Python Runner&lt;\/h1&gt;\n\n&lt;div class=\"row\"&gt;\n  &lt;form method=\"post\" enctype=\"multipart\/form-data\"&gt;\n    &lt;div&gt;&lt;b&gt;Upload a .py file&lt;\/b&gt;&lt;\/div&gt;\n    &lt;input type=\"file\" name=\"file\" accept=\".py\" required&gt;\n    &lt;button&gt;Upload&lt;\/button&gt;\n    &lt;div class=\"muted\"&gt;Saved to &lt;code&gt;scripts\/&lt;\/code&gt;. Only .py allowed.&lt;\/div&gt;\n  &lt;\/form&gt;\n\n  &lt;div class=\"list\"&gt;\n    &lt;div class=\"card\"&gt;\n      &lt;b&gt;Available scripts&lt;\/b&gt;\n      &lt;ul&gt;\n        &lt;?php if (!$files): ?&gt;\n          &lt;li class=\"muted\"&gt;No scripts yet. Upload above.&lt;\/li&gt;\n        &lt;?php else: foreach ($files as $f): ?&gt;\n          &lt;li&gt;\n            &lt;span class=\"name\"&gt;&lt;?=htmlspecialchars($f)?&gt;&lt;\/span&gt;\n            &lt;div class=\"actions\"&gt;\n              &lt;form method=\"post\" style=\"display:inline\"&gt;\n                &lt;input type=\"hidden\" name=\"run\" value=\"&lt;?=htmlspecialchars($f)?&gt;\"&gt;\n                &lt;button&gt;Run&lt;\/button&gt;\n              &lt;\/form&gt;\n              &lt;a href=\"&lt;?= 'scripts\/' . rawurlencode($f) ?&gt;\" download&gt;Download&lt;\/a&gt;\n            &lt;\/div&gt;\n          &lt;\/li&gt;\n        &lt;?php endforeach; endif; ?&gt;\n      &lt;\/ul&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/div&gt;\n\n&lt;?php if ($msg): ?&gt;\n  &lt;div class=\"card\" style=\"margin-top:16px\"&gt;&lt;?=$msg?&gt;&lt;\/div&gt;\n&lt;?php endif; ?&gt;\n\n&lt;?php if ($out): ?&gt;\n  &lt;div class=\"card\" style=\"margin-top:16px\"&gt;\n    &lt;b&gt;Output \u2014 &lt;?=htmlspecialchars($runFile)?&gt;&lt;\/b&gt;\n    &lt;div class=\"runout\"&gt;&lt;?=htmlspecialchars($out)?&gt;&lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;?php endif; ?&gt;\n\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Set <code>$PYTHON<\/code> to your venv Python if you have one (e.g. <code>\/home\/&lt;USER&gt;\/python\/venv\/bin\/python<\/code>).<br>Then go to <code>https:\/\/studio1live.com\/py_build\/<\/code> to use it.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Which one do I recommend?<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If you <strong>have<\/strong> \u201cSetup Python App\u201d in cPanel \u2192 <strong>Flask (Option 1)<\/strong> is cleaner and isolates Python nicely.<\/li>\n\n\n\n<li>If you <strong>don\u2019t<\/strong> \u2192 the <strong>PHP page (Option 2)<\/strong> works everywhere and is literally drop-in.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Quick reminders<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>That <code>python-3.13.1-amd64.exe<\/code> is a <strong>Windows installer<\/strong> \u2014 not for cPanel Linux. Ignore it here.<\/li>\n\n\n\n<li>Running arbitrary uploaded Python is powerful but risky. Keep the page private (restrict by IP or add a simple password) and <strong>never<\/strong> run untrusted code.<\/li>\n\n\n\n<li>I set a 20-second timeout and output truncation to avoid runaway scripts.<\/li>\n<\/ul>\n\n\n\n<p>If you tell me your real cPanel username (or just the last subfolder in your home path) I\u2019ll <strong>pre-fill the absolute paths<\/strong> in the files so you can paste and go.<\/p>\n\n\n\n<p>i was thinking to hide the upload folder, it can run only the files i upload on the server\/file manager end ,<\/p>\n\n\n\n<p>Thought for 8s<\/p>\n\n\n\n<p>Great idea. Easiest, safest setup: <strong>no web uploads at all<\/strong>. You\u2019ll place scripts using cPanel\u2019s File Manager (or SFTP), and the web page will only <strong>list &amp; run<\/strong> those server-side files.<\/p>\n\n\n\n<p>Below are two minimal setups (Flask or PHP) with uploads removed and the scripts folder <strong>hidden outside<\/strong> <code>public_html<\/code>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h1 class=\"wp-block-heading\">Folder layout (both options)<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/&lt;USER&gt;\/python\/py_build\/          \u2190 app lives here (outside public_html)\n\/home\/&lt;USER&gt;\/python\/py_build\/scripts\/  \u2190 your private .py files (no web access)\n\n\/home\/&lt;USER&gt;\/public_html\/py_build\/     \u2190 only the web endpoint lives here (if PHP option)\n\/home\/&lt;USER&gt;\/public_html\/              \u2190 public site files\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Put your <code>.py<\/code> scripts into: <code>\/home\/&lt;USER&gt;\/python\/py_build\/scripts\/<\/code><\/li>\n\n\n\n<li>That folder is not web-reachable.<\/li>\n\n\n\n<li>The UI will <strong>only list &amp; run<\/strong> files found there.<\/li>\n\n\n\n<li>You can further restrict access to the UI with Basic Auth (instructions below).<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h1 class=\"wp-block-heading\">Option A \u2014 Flask app (cPanel \u00bb Setup Python App)<\/h1>\n\n\n\n<p><strong>requirements.txt<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Flask==3.0.0\n<\/code><\/pre>\n\n\n\n<p><strong>app.py<\/strong> (no upload route; list+run only; token-protected run)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import os, re, subprocess\nfrom pathlib import Path\nfrom flask import Flask, request, render_template_string, redirect, url_for\n\n# Adjust these\nBASE_DIR = Path(__file__).resolve().parent\nSCRIPTS_DIR = BASE_DIR \/ \"scripts\"  # OUTSIDE public_html\nPYTHON_BIN = os.environ.get(\"PY_BUILD_PYTHON\", \"python3\")  # or full path to your venv\/bin\/python\nRUN_SECRET = os.environ.get(\"PY_BUILD_SECRET\", \"set-a-long-random-secret\")\nTIMEOUT_SECONDS = 20\nMAX_OUTPUT_BYTES = 200_000\n\nALLOWED = re.compile(r\"^[A-Za-z0-9_\\-\\.]+\\.py$\")\n\napp = Flask(__name__)\n\nHTML = \"\"\"\n&lt;!doctype html&gt;&lt;meta name=viewport content=\"width=device-width, initial-scale=1\"&gt;\n&lt;title&gt;Studio1Live \u2014 Python Runner&lt;\/title&gt;\n&lt;style&gt;\n body{font-family:system-ui,Segoe UI,Arial,sans-serif;padding:20px;max-width:900px;margin:auto}\n .card{border:1px solid #ddd;border-radius:12px;padding:16px;margin:10px 0}\n button{cursor:pointer;border:1px solid #333;border-radius:10px;padding:8px 14px;background:#111;color:#fff}\n .runout{white-space:pre-wrap;background:#111;color:#eee;padding:12px;border-radius:12px;overflow:auto;max-height:420px}\n .muted{color:#666}\n&lt;\/style&gt;\n&lt;h1&gt;Studio1Live \u2014 Python Runner&lt;\/h1&gt;\n&lt;div class=\"card\"&gt;\n  &lt;b&gt;Available scripts (server-managed)&lt;\/b&gt;\n  &lt;form method=\"post\" action=\"{{ url_for('run') }}\"&gt;\n    &lt;select name=\"filename\"&gt;\n      {% for f in files %}&lt;option value=\"{{f}}\"&gt;{{f}}&lt;\/option&gt;{% endfor %}\n      {% if not files %}&lt;option&gt;(none found)&lt;\/option&gt;{% endif %}\n    &lt;\/select&gt;\n    &lt;input type=\"password\" name=\"token\" placeholder=\"Run token\" required&gt;\n    &lt;button&gt;Run&lt;\/button&gt;\n    &lt;div class=\"muted\"&gt;Scripts folder: {{ scripts_dir }}&lt;\/div&gt;\n  &lt;\/form&gt;\n&lt;\/div&gt;\n{% if output is not none %}\n  &lt;div class=\"card\"&gt;\n    &lt;b&gt;Output \u2014 {{ filename }}&lt;\/b&gt;\n    &lt;div class=\"runout\"&gt;{{ output }}&lt;\/div&gt;\n  &lt;\/div&gt;\n{% endif %}\n\"\"\"\n\ndef list_scripts():\n    SCRIPTS_DIR.mkdir(exist_ok=True)\n    return sorted([p.name for p in SCRIPTS_DIR.glob(\"*.py\") if ALLOWED.match(p.name)])\n\n@app.get(\"\/\")\ndef home():\n    return render_template_string(HTML, files=list_scripts(), output=None, filename=None, scripts_dir=str(SCRIPTS_DIR))\n\n@app.post(\"\/run\")\ndef run():\n    token = request.form.get(\"token\",\"\")\n    if token != RUN_SECRET:\n        return redirect(url_for(\"home\"))\n\n    name = request.form.get(\"filename\",\"\")\n    if not ALLOWED.match(name):\n        return render_template_string(HTML, files=list_scripts(), output=\"[Error] Invalid filename.\", filename=name, scripts_dir=str(SCRIPTS_DIR))\n\n    script_path = SCRIPTS_DIR \/ name\n    if not script_path.exists():\n        return render_template_string(HTML, files=list_scripts(), output=\"[Error] File not found.\", filename=name, scripts_dir=str(SCRIPTS_DIR))\n\n    try:\n        result = subprocess.run([PYTHON_BIN, script_path.name], cwd=SCRIPTS_DIR, capture_output=True, text=True, timeout=TIMEOUT_SECONDS)\n        output = (result.stdout or \"\") + (\"\\n\"+result.stderr if result.stderr else \"\")\n    except subprocess.TimeoutExpired:\n        output = f\"[Error] Timed out after {TIMEOUT_SECONDS}s.\"\n    except Exception as e:\n        output = f\"[Error] {e}\"\n\n    if len(output.encode(\"utf-8\")) &gt; MAX_OUTPUT_BYTES:\n        output = output[:MAX_OUTPUT_BYTES] + \"\\n...\\n[truncated]\"\n\n    return render_template_string(HTML, files=list_scripts(), output=output, filename=name, scripts_dir=str(SCRIPTS_DIR))\n\n# cPanel \"Setup Python App\":\n#   App Directory: \/home\/&lt;USER&gt;\/python\/py_build\n#   Startup file: app.py\n#   Entry point: app\n#   Environment variables (set in cPanel):\n#     PY_BUILD_PYTHON = \/home\/&lt;USER&gt;\/.venv\/bin\/python   (if using a venv)\n#     PY_BUILD_SECRET = &lt;long random token&gt;\n<\/code><\/pre>\n\n\n\n<p><strong>Steps:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>In cPanel \u2192 <strong>Setup Python App<\/strong>: create app (Python 3.9+), App Directory <code>\/home\/&lt;USER&gt;\/python\/py_build<\/code>.<\/li>\n\n\n\n<li>Set <strong>Startup file:<\/strong> <code>app.py<\/code> and <strong>Entry point:<\/strong> <code>app<\/code>.<\/li>\n\n\n\n<li>Click <strong>Enter to virtual environment<\/strong> \u2192 <code>pip install Flask==3.0.0<\/code>.<\/li>\n\n\n\n<li>Set two <strong>Environment Variables<\/strong> (in the app page):\n<ul class=\"wp-block-list\">\n<li><code>PY_BUILD_SECRET<\/code> = long random string (you type this to run scripts)<\/li>\n\n\n\n<li><code>PY_BUILD_PYTHON<\/code> = path to your desired Python (optional)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Restart the app.<\/li>\n\n\n\n<li>Map URL to your app (cPanel usually does this). Visit: <code>https:\/\/studio1live.com\/py_build<\/code><\/li>\n\n\n\n<li>Place scripts in <code>\/home\/&lt;USER&gt;\/python\/py_build\/scripts\/<\/code> via File Manager\/SFTP.<\/li>\n\n\n\n<li>On the page: choose script \u2192 enter token \u2192 Run.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h4 class=\"wp-block-heading\">Option B \u2014 PHP page (no uploads, no public script access)<\/h4>\n\n\n\n<p><strong>Folder:<\/strong> <code>\/home\/&lt;USER&gt;\/public_html\/py_build\/<\/code><\/p>\n\n\n\n<p><strong>index.php<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\/\/ List+Run only. No uploads. Scripts live outside public_html.\n$PYTHON = '\/usr\/local\/bin\/python3'; \/\/ or '\/home\/&lt;USER&gt;\/python\/venv\/bin\/python'\n$SCRIPTS_DIR = '\/home\/&lt;USER&gt;\/python\/py_build\/scripts';\n$RUN_SECRET = 'set-a-long-random-secret';\n\nfunction allowed($name){ return preg_match('\/^[A-Za-z0-9_\\-\\.]+\\.py$\/', $name); }\n\n$files = [];\nif (is_dir($SCRIPTS_DIR)) {\n  foreach (scandir($SCRIPTS_DIR) as $f) if (allowed($f)) $files[] = $f;\n}\n$out = ''; $runFile = '';\n\nif ($_SERVER['REQUEST_METHOD']==='POST' &amp;&amp; isset($_POST['filename'], $_POST['token'])) {\n  if ($_POST['token'] !== $RUN_SECRET) {\n    $out = \"[Error] Unauthorized.\";\n  } else {\n    $runFile = basename($_POST['filename']);\n    if (allowed($runFile) &amp;&amp; file_exists(\"$SCRIPTS_DIR\/$runFile\")) {\n      $cmd = escapeshellcmd($PYTHON).' '.escapeshellarg($runFile);\n      $desc = [0=&gt;[\"pipe\",\"r\"],1=&gt;[\"pipe\",\"w\"],2=&gt;[\"pipe\",\"w\"]];\n      $proc = proc_open($cmd, $desc, $pipes, $SCRIPTS_DIR);\n      if (is_resource($proc)) {\n        fclose($pipes[0]);\n        $stdout = stream_get_contents($pipes[1]); fclose($pipes[1]);\n        $stderr = stream_get_contents($pipes[2]); fclose($pipes[2]);\n        $code = proc_close($proc);\n        $out = $stdout . ($stderr ? \"\\n\".$stderr : '');\n        if (strlen($out) &gt; 200000) $out = substr($out, 0, 200000).\"\\n...\\n[truncated]\";\n      } else { $out = \"[Error] Could not execute.\"; }\n    } else { $out = \"Invalid file.\"; }\n  }\n}\n?&gt;\n&lt;!doctype html&gt;\n&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"&gt;\n&lt;title&gt;Studio1Live \u2014 Python Runner&lt;\/title&gt;\n&lt;style&gt;\n body{font-family:system-ui,Segoe UI,Arial,sans-serif;padding:20px;max-width:900px;margin:auto}\n .card{border:1px solid #ddd;border-radius:12px;padding:16px;margin:10px 0}\n button{cursor:pointer;border:1px solid #333;border-radius:10px;padding:8px 14px;background:#111;color:#fff}\n .runout{white-space:pre-wrap;background:#111;color:#eee;padding:12px;border-radius:12px;overflow:auto;max-height:420px}\n .muted{color:#666}\n&lt;\/style&gt;\n&lt;h1&gt;Studio1Live \u2014 Python Runner&lt;\/h1&gt;\n&lt;div class=\"card\"&gt;\n  &lt;form method=\"post\"&gt;\n    &lt;label&gt;&lt;b&gt;Script&lt;\/b&gt;\n      &lt;select name=\"filename\"&gt;\n        &lt;?php foreach ($files as $f): ?&gt;\n          &lt;option value=\"&lt;?=htmlspecialchars($f)?&gt;\"&gt;&lt;?=htmlspecialchars($f)?&gt;&lt;\/option&gt;\n        &lt;?php endforeach; ?&gt;\n      &lt;\/select&gt;\n    &lt;\/label&gt;\n    &lt;label&gt; &lt;b&gt;Token&lt;\/b&gt;\n      &lt;input type=\"password\" name=\"token\" required&gt;\n    &lt;\/label&gt;\n    &lt;button&gt;Run&lt;\/button&gt;\n    &lt;div class=\"muted\"&gt;Scripts folder: &lt;?=htmlspecialchars($SCRIPTS_DIR)?&gt;&lt;\/div&gt;\n  &lt;\/form&gt;\n&lt;\/div&gt;\n\n&lt;?php if ($out): ?&gt;\n  &lt;div class=\"card\"&gt;\n    &lt;b&gt;Output \u2014 &lt;?=htmlspecialchars($runFile)?&gt;&lt;\/b&gt;\n    &lt;div class=\"runout\"&gt;&lt;?=htmlspecialchars($out)?&gt;&lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;?php endif; ?&gt;\n<\/code><\/pre>\n\n\n\n<p><strong>What this does<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Shows a dropdown of <code>.py<\/code> files in <code>\/home\/&lt;USER&gt;\/python\/py_build\/scripts\/<\/code><\/li>\n\n\n\n<li>Requires a <strong>token<\/strong> to run<\/li>\n\n\n\n<li>Executes with a timeout inherited from PHP execution limits<\/li>\n\n\n\n<li>No upload or download; everything stays private<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Extra hardening (recommended)<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Basic Auth<\/strong> on <code>\/py_build<\/code> (PHP option) or the Flask route.<br>In <code>\/home\/&lt;USER&gt;\/public_html\/py_build\/.htaccess<\/code>: <code>AuthType Basic AuthName \"Restricted\" AuthUserFile \/home\/&lt;USER&gt;\/.htpasswd Require valid-user<\/code> Then create <code>.htpasswd<\/code> in your home dir with <code>htpasswd<\/code> or an online generator.<\/li>\n\n\n\n<li><strong>Whitelist<\/strong> specific scripts: replace the dropdown with a <strong>hardcoded list<\/strong> of allowed filenames.<\/li>\n\n\n\n<li><strong>Logging:<\/strong> append <code>date + filename + exit code<\/code> to a private log file in your home dir.<\/li>\n\n\n\n<li><strong>Permissions:<\/strong> <code>scripts\/<\/code> should be owned by your user and set to <code>700<\/code> if you want to restrict even more.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Your workflow (no uploads over web)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <strong>cPanel File Manager<\/strong> or SFTP to put <code>*.py<\/code> into: <code>\/home\/&lt;USER&gt;\/python\/py_build\/scripts\/<\/code><\/li>\n\n\n\n<li>Go to:\n<ul class=\"wp-block-list\">\n<li>Flask: <code>https:\/\/studio1live.com\/py_build<\/code><\/li>\n\n\n\n<li>PHP: <code>https:\/\/studio1live.com\/py_build\/<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Choose a script \u2192 enter token \u2192 <strong>Run<\/strong> \u2192 see output.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Security<\/h2>\n\n\n\n<p>\ud83d\udc4d<\/p>\n\n\n\n<p>Let\u2019s clarify what\u2019s happening and why I suggested the token:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d What the token is for<\/h3>\n\n\n\n<p>The token isn\u2019t about other files on your server \u2014 it\u2019s about <strong>web access<\/strong>.<\/p>\n\n\n\n<p>If someone knows (or guesses) that <code>studio1live.com\/py_build<\/code> exists, and there\u2019s a \u201cRun\u201d button that executes any <code>.py<\/code> file in <code>\/py_build\/scripts<\/code>, that person could:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Visit that page,<\/li>\n\n\n\n<li>Pick one of your script names (which are listed),<\/li>\n\n\n\n<li>Click \u201cRun\u201d \u2014 and your server would execute that code.<\/li>\n<\/ul>\n\n\n\n<p>Even though they <strong>can\u2019t upload new <code>.py<\/code> files<\/strong>, they could still run <strong>the existing ones<\/strong> if the page doesn\u2019t require any kind of key, password, or token.<\/p>\n\n\n\n<p>So:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The <strong>token<\/strong> (or password) simply makes sure <em>only you<\/em> can run code.<\/li>\n\n\n\n<li>It\u2019s <strong>not<\/strong> about hidden folders or blocking the file system \u2014 your <code>\/py_build\/scripts\/<\/code> folder is already secure (since it\u2019s outside <code>public_html<\/code>).<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Simplest secure setup (what you want)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>\/home\/&lt;USER&gt;\/python\/py_build\/scripts\/<\/code> \u2192 you upload <code>.py<\/code> files here via File Manager.<\/li>\n\n\n\n<li><code>\/home\/&lt;USER&gt;\/public_html\/py_build\/<\/code> \u2192 has your runner page (<code>index.php<\/code> or Flask app).<\/li>\n\n\n\n<li>The page <strong>lists only those files<\/strong>, and <strong>only you<\/strong> can run them (via token or HTTP password).<\/li>\n<\/ul>\n\n\n\n<p>You can protect it in one of three easy ways:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Option 1: Keep the token (easiest)<\/h4>\n\n\n\n<p>Only someone with the token can execute any file.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Think of it as a quick password check before running.<\/p>\n<\/blockquote>\n\n\n\n<h4 class=\"wp-block-heading\">Option 2: Use cPanel password protection<\/h4>\n\n\n\n<p>Go to <strong>cPanel \u2192 Directory Privacy<\/strong>, find <code>\/public_html\/py_build\/<\/code>, and add a username\/password.<br>That\u2019s classic <code>.htaccess<\/code> protection \u2014 no need for a token in the page.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Option 3: Hard-code allowed scripts<\/h4>\n\n\n\n<p>If you just need to run 2\u20133 known scripts, the page can skip the dropdown and have fixed \u201cRun A \/ Run B\u201d buttons \u2014 nobody can trigger others.<\/p>\n<\/body>","protected":false},"excerpt":{"rendered":"<p>Python Runner Web Template: Build Self-Hosted Python Tools on Your Website (No SaaS Required) Meta Description (Yoast \/ RankMath):Deploy Python tools directly on your website with Python Runner Web Template. Run scripts, generate PDFs, automate workflows, and stay fully self-hosted. Introduction: Python Tools Belong on Your Website Most online tools today force creators into a &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/fixyourowncredit.studio1live.com\/downloads\/python-runner-web-template\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Python Runner Web Template&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-906","post","type-post","status-publish","format-standard","hentry","category-uncategorized","entry"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/posts\/906","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/comments?post=906"}],"version-history":[{"count":3,"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/posts\/906\/revisions"}],"predecessor-version":[{"id":1132,"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/posts\/906\/revisions\/1132"}],"wp:attachment":[{"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/media?parent=906"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/categories?post=906"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fixyourowncredit.studio1live.com\/downloads\/wp-json\/wp\/v2\/tags?post=906"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}