Mastering the Command Line: Efficient Python Script Execution on Linux
Script execution failures in production often trace back to misunderstandings about the Linux environment—wrong interpreter, permissions, environment contamination. This concise guide outlines established best practices for running Python scripts reliably on Linux.
Python Availability and Version Control
Most current distributions (Ubuntu 22.04 LTS, CentOS 8+) ship with Python 3.x, but legacy systems (CentOS 7, RHEL 7, earlier Ubuntu releases) may default to Python 2.x. Always verify:
python3 --version # Preferred. Expect output: Python 3.10.12
If absent/incorrect:
sudo apt update && sudo apt install python3 # Debian/Ubuntu
sudo dnf install python3 # RHEL/CentOS/Fedora
Note: Avoid relying on python
; on many systems this invokes Python 2.x or throws:
Command 'python' not found, did you mean:
command 'python3' from deb python3
Minimal Example: Scripting and Execution
Consider the operational need to run a maintenance script from cron. Place hello.py
in /opt/scripts/
:
#!/usr/bin/env python3
print("Scheduled job: Success")
Key steps:
chmod +x /opt/scripts/hello.py
/opt/scripts/hello.py
Output should resemble:
Scheduled job: Success
Shebang (#!…
) enables direct execution. Use /usr/bin/env python3
for environment portability (virtualenv support, user-installed interpreters).
Passing Command-Line Arguments
Production scripts rarely run without parameters. Typical pattern:
#!/usr/bin/env python3
import sys
if len(sys.argv) < 2:
print("Usage: hello.py <username>")
exit(1)
user = sys.argv[1]
print(f"Welcome, {user}")
Invoke:
./hello.py sysadmin
Yields:
Welcome, sysadmin
Gotcha: If called from another working directory, relative file references within the script may fail. Normalize with os.path.abspath(os.path.dirname(__file__))
for robust path resolution.
Executing as a Module
When packaging as part of a collection:
python3 -m mypackage.hello
Module execution enforces import context, raising ModuleNotFoundError
if the structure is not correct:
ModuleNotFoundError: No module named 'mypackage'
Useful for CI jobs or deployment hooks where import paths must be validated.
$PATH, Environment, and Permissions
To run a script globally (e.g., hello.py
from any directory):
-
Place script in
$HOME/bin
or/usr/local/bin
. -
Ensure it's executable:
chmod 755 hello.py
-
Set PATH if needed:
export PATH="$HOME/bin:$PATH"
-
Persist in
.bashrc
,.zshrc
, or profile equivalent.
Known issue: Modifying /usr/local/bin
typically requires root privileges. Consider security implications for multi-user systems.
Handling Python Environments
System Python often collides with user requirements. Use venv
for isolation:
python3 -m venv /opt/myjobenv
source /opt/myjobenv/bin/activate
pip install requests
python /opt/scripts/hello.py
deactivate
Only dependencies for that environment are available. Outside, system Python is unaffected.
Side note: Scripts with hardcoded /usr/bin/python3
in the shebang ignore venv
activation. Prefer /usr/bin/env python3
unless you have a static, site-wide Python.
Practical Edge Cases
-
Cron jobs: Use absolute paths, set
PATH
variable explicitly. Cron runs with minimal environment; missing variables (e.g.,PYTHONPATH
) result in cryptic errors. -
SELinux/AppArmor: On hardened systems,
Permission denied
error persists even with correctchmod
. Audit logs clarify (/var/log/audit/audit.log
,journalctl -xe
). -
Line endings: Windows line endings (
^M
errors) break scripts. Convert withdos2unix
:dos2unix hello.py
-
Dependency drift: Pin requirements using
requirements.txt
orpip freeze > requirements.txt
for recurring batch jobs.
Quick Reference Table
Task | Command/Setting | Note |
---|---|---|
Check version | python3 --version | Check actual interpreter used |
Make executable | chmod +x yourscript.py | Needed for shebang execution |
Shebang (portable) | #!/usr/bin/env python3 | Supports venvs, user installs |
Add to PATH | export PATH="$HOME/bin:$PATH" | Use in shell rc files |
Create venv | python3 -m venv venvdir | Project-specific deps |
Install package | pip install -r requirements.txt | Pin and track dependencies |
Non-Obvious Tip
Use set -euo pipefail
in bash scripts that call Python code during automation. This ensures upstream failures are correctly caught, avoiding silent data corruption or missed tasks.
Linux script execution is rarely just about the command syntax—it’s about knowing system defaults, environment pitfalls, and ensuring scripts behave as expected under automation, not just interactive use. That’s what separates a reliable deployment from a flaky one.