Add tech_docs/python/python_style_guide.md
This commit is contained in:
232
tech_docs/python/python_style_guide.md
Normal file
232
tech_docs/python/python_style_guide.md
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
Sure, here's a comprehensive shell (Bash) scripting standards document, aligned with the principles and structure we established for the HTML standards.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
# Shell (Bash) Scripting Standards Documentation
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This document outlines our conventions and best practices for writing **Shell (Bash) scripts**. Adhering to these standards ensures our scripts are **consistent, readable, maintainable, and robust**. By following these guidelines, we'll foster **easier collaboration**, **reduce debugging time**, and **improve script reliability**.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
## Script Structure and Headers
|
||||||
|
|
||||||
|
Consistent script structure and informative headers are crucial for immediate understanding and maintainability.
|
||||||
|
|
||||||
|
* **Shebang Line**: Always start with the shebang line specifying the interpreter.
|
||||||
|
* **Description**: Ensures the script runs with Bash, regardless of the user's default shell.
|
||||||
|
* **Usage**: `#!/bin/bash`
|
||||||
|
* **Script Header Comments**: Include a standardized block at the top of each script.
|
||||||
|
* **Description**: Provides essential metadata for quick reference.
|
||||||
|
* **Usage**:
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script Name: myscript.sh
|
||||||
|
# Description: This script automates the backup of project files.
|
||||||
|
# Author: Your Name <your.email@example.com>
|
||||||
|
# Date: 2025-06-30
|
||||||
|
# Version: 1.0.0
|
||||||
|
# Usage: ./myscript.sh [--options] <arguments>
|
||||||
|
# Dependencies: rsync, tar
|
||||||
|
# License: MIT (or your chosen license)
|
||||||
|
```
|
||||||
|
* **Error Handling (Immediate Exit)**:
|
||||||
|
* **Description**: Always include `set -e` and `set -u`.
|
||||||
|
* `set -e`: Exit immediately if a command exits with a non-zero status. This prevents scripts from continuing in an error state.
|
||||||
|
* `set -u`: Treat unset variables as an error and exit immediately. This helps catch typos and uninitialized variables.
|
||||||
|
* `set -o pipefail`: (Optional but recommended) Causes a pipeline to return the exit status of the last command in the pipe that exited with a non-zero status, rather than just the last command.
|
||||||
|
* **Usage**:
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail # All three combined
|
||||||
|
```
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
## Naming Conventions
|
||||||
|
|
||||||
|
Consistent naming makes variables, functions, and files easy to identify and understand.
|
||||||
|
|
||||||
|
### 1\. Variables
|
||||||
|
|
||||||
|
* **Lowercase with Underscores (snake\_case)**:
|
||||||
|
* **Description**: For general script variables.
|
||||||
|
* **Usage**: `file_name`, `user_input`, `temp_directory`
|
||||||
|
* **Uppercase with Underscores (SCREAMING\_SNAKE\_CASE)**:
|
||||||
|
* **Description**: For **constants** (values that should not change) and **environment variables**.
|
||||||
|
* **Usage**: `MAX_RETRIES=5`, `LOG_FILE="/var/log/app.log"`, `PATH`
|
||||||
|
* **Positional Parameters**:
|
||||||
|
* **Description**: Refer to script arguments using `$1`, `$2`, etc., and use `$@` for all arguments.
|
||||||
|
* **Usage**: `echo "First arg: $1"`, `for arg in "$@"; do ... done`
|
||||||
|
|
||||||
|
### 2\. Functions
|
||||||
|
|
||||||
|
* **Lowercase with Underscores (snake\_case)**:
|
||||||
|
* **Description**: For function names. Verb-noun structure is often helpful.
|
||||||
|
* **Usage**: `display_help`, `process_file`, `cleanup_temp_files`
|
||||||
|
|
||||||
|
### 3\. Files
|
||||||
|
|
||||||
|
* **Lowercase with Hyphens (kebab-case)**:
|
||||||
|
* **Description**: For script filenames. Avoid spaces.
|
||||||
|
* **Usage**: `backup-database.sh`, `deploy-app.sh`, `monitor-logs.sh`
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
## Formatting and Readability
|
||||||
|
|
||||||
|
Clean formatting significantly improves readability and navigability.
|
||||||
|
|
||||||
|
### 1\. Indentation
|
||||||
|
|
||||||
|
* **Spaces over Tabs**:
|
||||||
|
* **Description**: Use **4 spaces** for indentation. Configure your editor to convert tabs to spaces.
|
||||||
|
* **Consistent Indentation**:
|
||||||
|
* **Description**: Indent blocks of code within `if`, `for`, `while`, `function`, etc. consistently.
|
||||||
|
|
||||||
|
### 2\. Spacing
|
||||||
|
|
||||||
|
* **Operators and Assignments**:
|
||||||
|
* **Description**: Use spaces around operators (`=`, `==`, `!=`, `<`, `>`) and assignments.
|
||||||
|
* **Usage**: `variable = "value"`, `if [[ $a -eq $b ]]`, `count=$((count + 1))`
|
||||||
|
* **Function Calls**:
|
||||||
|
* **Description**: No space between function name and parentheses.
|
||||||
|
* **Usage**: `my_function arg1 arg2` (not `my_function(arg1, arg2)`)
|
||||||
|
* **Command Separators**:
|
||||||
|
* **Description**: Use semicolons `;` only for multiple commands on one line, or for simple `if` statements. Prefer new lines.
|
||||||
|
* **Usage**: `command1; command2` (less common), `if [ "$1" == "--help" ]; then display_help; exit 0; fi`
|
||||||
|
|
||||||
|
### 3\. Comments
|
||||||
|
|
||||||
|
* **Descriptive Comments**:
|
||||||
|
* **Description**: Use `#` for single-line comments. Add comments to explain **why** a piece of code exists, not just **what** it does. Complex logic or non-obvious steps should be commented.
|
||||||
|
* **Usage**:
|
||||||
|
```bash
|
||||||
|
# Validate that the log file exists before proceeding.
|
||||||
|
if [[ ! -f "$LOG_FILE" ]]; then
|
||||||
|
echo "Error: Log file not found at $LOG_FILE" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
* **Block Comments**:
|
||||||
|
* **Description**: For larger explanations or section headers.
|
||||||
|
* **Usage**:
|
||||||
|
```bash
|
||||||
|
#############################################
|
||||||
|
# Function: cleanup_old_backups
|
||||||
|
# Description: Deletes backups older than N days.
|
||||||
|
#############################################
|
||||||
|
```
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
## Best Practices and Principles
|
||||||
|
|
||||||
|
These principles guide our overall approach to writing effective and maintainable Bash scripts.
|
||||||
|
|
||||||
|
### 1\. Modularity and Functions
|
||||||
|
|
||||||
|
* **Description**: Break down complex scripts into smaller, focused functions. Each function should perform a single, well-defined task.
|
||||||
|
* **Benefit**: Improves readability, reusability, and makes debugging easier.
|
||||||
|
* **Usage**:
|
||||||
|
```bash
|
||||||
|
function validate_input() {
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
echo "Error: Argument is missing." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
validate_input "$@"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2\. Argument Parsing
|
||||||
|
|
||||||
|
* **Description**: For scripts that accept options or arguments, use `getopts` for simple options or manual parsing for more complex scenarios. Avoid simple positional checks for multiple options.
|
||||||
|
* **Benefit**: Provides a user-friendly interface and robust argument handling.
|
||||||
|
* **Usage (`getopts` example)**:
|
||||||
|
```bash
|
||||||
|
while getopts "hv:d:" opt; do
|
||||||
|
case $opt in
|
||||||
|
h) display_help; exit 0 ;;
|
||||||
|
v) VERBOSE=true ;;
|
||||||
|
d) DEST_DIR="$OPTARG" ;;
|
||||||
|
\?) echo "Invalid option: -$OPTARG" >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift $((OPTIND - 1)) # Shift positional parameters
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3\. Error Handling and Logging
|
||||||
|
|
||||||
|
* **Description**: Beyond `set -e` and `set -u`, implement explicit error checks for critical commands. Redirect error messages to `stderr` (`>&2`) and informative messages to `stdout`. Consider logging to a file for long-running scripts.
|
||||||
|
* **Benefit**: Makes scripts more robust and easier to diagnose issues.
|
||||||
|
* **Usage**:
|
||||||
|
```bash
|
||||||
|
# Command that might fail
|
||||||
|
cp source_file.txt dest_dir/ || { echo "Error: Failed to copy file." >&2; exit 1; }
|
||||||
|
|
||||||
|
log_message() {
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_message "Script started."
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4\. Quoting Variables
|
||||||
|
|
||||||
|
* **Description**: **Always quote variables** when they contain spaces or special characters to prevent word splitting and globbing. This is one of the most common Bash pitfalls.
|
||||||
|
* **Benefit**: Prevents unexpected behavior and ensures commands receive arguments as intended.
|
||||||
|
* **Usage**:
|
||||||
|
```bash
|
||||||
|
# BAD: May cause issues if file has spaces
|
||||||
|
# rm $FILE_PATH
|
||||||
|
|
||||||
|
# GOOD: Safely handles spaces
|
||||||
|
rm "$FILE_PATH"
|
||||||
|
|
||||||
|
# For arrays
|
||||||
|
for item in "${my_array[@]}"; do
|
||||||
|
echo "$item"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5\. Using `[[ ... ]]` over `[ ... ]` (where appropriate)
|
||||||
|
|
||||||
|
* **Description**: Prefer the `[[ ... ]]` (Bash's extended test command) for conditional expressions over the older `[ ... ]` (POSIX `test` command).
|
||||||
|
* **Benefit**: `[[ ... ]]` offers more features (like regex matching `==~`, logical operators `&&`, `||`), is less prone to word splitting issues, and provides better readability.
|
||||||
|
* **Usage**:
|
||||||
|
```bash
|
||||||
|
if [[ "$variable" == "expected value" ]]; then ... fi
|
||||||
|
if [[ "$string" =~ ^[0-9]+$ ]]; then echo "Is a number"; fi
|
||||||
|
if [[ -f "$file" && -r "$file" ]]; then ... fi
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6\. Avoid `ls` Parsing
|
||||||
|
|
||||||
|
* **Description**: Do not parse the output of `ls` (e.g., using `grep` or `awk` on `ls` output) for processing filenames. `ls` output is for human readability, not programmatic use, and can be ambiguous with special characters.
|
||||||
|
* **Benefit**: Prevents subtle bugs when dealing with filenames containing spaces, newlines, or other special characters.
|
||||||
|
* **Instead**: Use globbing or `find -print0 | xargs -0` for safe file processing.
|
||||||
|
* **Usage**:
|
||||||
|
```bash
|
||||||
|
# BAD: Don't do this!
|
||||||
|
# for file in $(ls *.txt); do ... fi
|
||||||
|
|
||||||
|
# GOOD: Use globbing
|
||||||
|
for file in *.txt; do
|
||||||
|
echo "Processing '$file'"
|
||||||
|
done
|
||||||
|
|
||||||
|
# GOOD: For complex find operations
|
||||||
|
find . -name "*.log" -print0 | while IFS= read -r -d $'\0' file; do
|
||||||
|
echo "Found log: $file"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
By diligently applying these **Bash scripting standards**, we ensure our scripts are not only functional but also **highly readable, maintainable, and robust**. This commitment to quality coding practices promotes a more efficient development workflow and strengthens the reliability of our automated tasks.
|
||||||
Reference in New Issue
Block a user