How To Run Python Script Linux

How To Run Python Script Linux

Reading time1 min
#Python#Linux#Automation#VirtualEnvironments#CronJobs#Systemd

Mastering Python Script Execution in Linux: Practical Patterns Beyond the Basics

Invoking python3 myscript.py is sufficient for quick debugging—but what about production deployments, repeatability, or non-interactive environments? Python script execution on Linux is rarely that simple once requirements grow.

This guide covers execution patterns essential for maintainable, robust automation using Python on Linux. Topics: direct invocation, execution context, dependency isolation, scheduling, and persistent service operation.


Direct Execution: Using Shebang for CLI Integration

Python utilities should feel like any native Linux command.

Add a shebang:

#!/usr/bin/env python3
# main logic below

/usr/bin/env selects the interpreter found first in $PATH, mitigating discrepancies between distributions or multiple installed Python versions.

Make script executable:

chmod +x myscript.py
./myscript.py

Real-world side note:
Packaging Python CLI tools this way allows drop-in use inside shell scripts, containers, or automated jobs—no need for explicit interpreter calls.

Gotcha:
Avoid spaces or control characters before the shebang. Broken shebangs produce cryptic errors (bad interpreter: No such file or directory).


Dependency Isolation: Virtual Environments Preferred

Python system packages (/usr/lib/python3.*) are frequently out of sync with application needs. This mismatch causes “works on my machine” failures, even in CI/CD.

Create and activate a venv:

python3.10 -m venv ~/venvs/myproj
source ~/venvs/myproj/bin/activate
pip install requests==2.28.2

For stricter control:
Pin all dependencies in requirements.txt. For reproducibility, export with hashes via pip-compile if you're serious:

pip freeze --all > requirements.txt

or, for even more reliability:

pip install pip-tools
pip-compile --generate-hashes requirements.in

Refined invocation options:

  • Embed absolute interpreter in the shebang:
    #!/home/user/venvs/myproj/bin/python
    
  • Or always activate the venv before running:
    source ~/venvs/myproj/bin/activate
    ./myscript.py
    
    Note: Hardcoded paths in shebangs break if the virtual environment moves. env will not pick up venvs unless they're activated.

Non-Interactive & Scheduled Execution

Scheduling via Cron

Cron jobs trim away shell niceties—minimal $PATH, no profile scripts. Config errors surface as silent failures.

Set up a cron job:

0 2 * * * /home/user/venvs/myproj/bin/python /data/scripts/daily_report.py >>/var/log/daily_report.log 2>&1

Critical detail:
Always use absolute paths for Python, scripts, and logs. Cron may not inherit your environment variables or paths.

Example of a missing dependency issue in cron log:

Traceback (most recent call last):
  ModuleNotFoundError: No module named 'requests'

This almost always means the script ran under the wrong interpreter or outside the expected environment.

Persistent Execution via systemd

Systemd brings resurrection—automatic restarts, logging, PID tracking, resource controls.

Sample unit file (/etc/systemd/system/myscript.service):

[Unit]
Description=Periodic ingest worker
After=network.target

[Service]
User=svcuser
WorkingDirectory=/opt/ingest/
EnvironmentFile=-/etc/default/ingest.env
ExecStart=/home/svcuser/venvs/ingest/bin/python /opt/ingest/worker.py
Restart=on-failure
RestartSec=5
StandardOutput=append:/var/log/ingest.log
StandardError=journal

[Install]
WantedBy=multi-user.target

Reload and enable:

sudo systemctl daemon-reload
sudo systemctl start myscript.service
sudo systemctl enable myscript.service

Known issue:
Log rotation for stdout isn't automatic. Integrate logrotate or set up journald policies for sustained operation.


Environment Variables: Explicit Is Safer

Production and scheduled environments often lack the expected variables. Failures due to missing secrets are common, e.g.:

ValueError: API_KEY environment variable not set

Solutions:

  • Export critical variables within the cron file:
    API_KEY=abcd1234
    0 * * * * /home/user/venvs/myproj/bin/python /data/scripts/fetch.py
    
  • Use an .env loader (e.g., python-dotenv) or source shell exports from a wrapper script:
    #!/bin/bash
    set -a
    source /etc/myapp.env
    set +a
    exec /home/user/venvs/myproj/bin/python /data/scripts/fetch.py "$@"
    

Optimizing Script Start: Bytecode & Compilation

Short-lived scripts (frequent in batch or CI environments) often waste milliseconds on interpreter startup.

Precompile to bytecode:

python3 -m py_compile myscript.py

Python then executes the .pyc file directly, bypassing parsing.

Alternative:
Build a native executable for distribution via Nuitka or PyInstaller. Overkill for most in-house usage, but sometimes necessary for locked-down environments or minimal Docker images—for example, Alpine Linux with musl (python:alpine).


Execution Checklist: Running Python Reliably in Linux Environments

PatternAction/CommandKey Benefit
Shebang + chmod#!/usr/bin/env python3 + chmod +xNative script execution
Virtualenv Isolationpython3 -m venv v / activate / explicit pathsNo dependency clashes
Cron/SystemdSetup job/service with absolute pathsReliable scheduling, auto-restart
Env Vars ExplicitAPI_KEY=..., use .env or exportFewer missing-config failures
Pre-compilationpython3 -m py_compile or nuitkaFaster, portable deployments

Engineer’s note:
For production, always monitor logs for silent terminations. Test scheduled jobs under the exact user/environment as live deployment to avoid “invisible” failures.


Well-crafted Python execution workflows on Linux separate toy scripts from robust automation. Skip one of these patterns, and that silent cron failure or missing dependency will remind you—painfully—where reliability originates.

For advanced use: containerize scripts and run via orchestrators like systemd-nspawn or directly under Kubernetes Jobs. But even there: shebang, env, and paths still matter.