Core Python Syntax for Scripting

Core Python syntax for scripting — Python for DevOps automation.

Focus: core python syntax for scripting

Sponsored

You’ve written a few Python one-liners and maybe a loop or two, but now you need to write a real script that can parse a log file, deploy an app, or check a service health — and you feel stuck on the syntax that makes Python scripts actually work in production. This lesson teaches you the core Python syntax for scripting — the exact constructs you’ll use in every DevOps automation script you write. From variables and loops to error handling and file I/O, you’ll build a mental model that turns Python from a toy into a tool.

The problem this lesson solves

When you first dive into Python, you learn pieces: a for loop here, a dict there, a print() everywhere. But real-world automation scripts require you to combine all of those pieces into a single coherent program. The pain is real: you start a script, hit a NameError because you misspelled a variable, then a TypeError because you mixed strings and integers, and then you give up and go back to shell scripts.

This lesson exists to solve that. It gives you the core syntax — the grammar of Python — so you can write scripts that are readable, maintainable, and deterministic. We’re not covering every obscure feature; we’re covering the 20% of syntax that you’ll use 80% of the time in DevOps automation. By the end, you’ll be able to write a script that reads a configuration file, processes a list of servers, and logs results — all with confident Python syntax.

Core concept / mental model

Think of a Python script as a sequence of instructions executed from top to bottom. The syntax is the grammar that tells the Python interpreter how to structure those instructions. Two core concepts dominate: indentation and data types.

  • Indentation (usually 4 spaces) defines blocks of code — it’s not optional, it’s the language’s way of grouping statements. If you’ve used curly braces in other languages, think of indentation as your {}.
  • Data types — strings, integers, floats, booleans, lists, dicts, and tuples — define what kind of data you’re manipulating. Many syntax errors come from trying to use the wrong operation on the wrong type.

Here’s a simple mental model for a script:

[input] → [process with variables, loops, conditionals] → [output]

Everything in a script is either input (files, arguments, environment), processing (logic), or output (print, write to file, API call). The syntax is how you express each part.

How it works step by step

Let’s walk through the essential syntax constructs in the order you’ll likely use them in a script.

1. Variables and assignment

In Python, you don’t declare types — you assign values, and the type is inferred. Use = for assignment. Variable names should be snake_case.

server_name = "web-01"
port = 8080
is_healthy = True

2. Conditionals: if, elif, else

Control flow uses if, elif, and else with a colon and indented block. Note the syntax: if condition: and then an indented block.

if status_code == 200:
    print("OK")
elif status_code == 404:
    print("Not Found")
else:
    print("Error:", status_code)

3. Loops: for and while

for loops iterate over sequences (lists, tuples, dicts, strings, ranges). while loops repeat as long as a condition is true. Use break to exit early and continue to skip an iteration.

for server in ["web-01", "web-02", "db-01"]:
    print("Checking", server)

count = 0
while count < 3:
    print("Retry", count)
    count += 1

4. Functions: def

Functions let you reuse logic. Define with def function_name(parameters): and return a value with return.

def get_status(server):
    # Simulate an HTTP check
    return 200

status = get_status("web-01")
print(status)  # Output: 200

5. Data structures: lists and dicts

Lists are ordered, mutable collections (use brackets []). Dicts map keys to values (use braces {}). Both are core to scripting.

servers = ["web-01", "web-02"]
config = {
    "port": 8080,
    "debug": False
}

print(config["port"])  # Output: 8080

6. String formatting (f-strings)

f-strings (formatted string literals) are the modern way to embed variables in strings. Use f"{variable}".

name = "web-01"
print(f"Server: {name}")

7. Error handling: try/except

Robust scripts handle failures gracefully using try/except. Wrap risky operations and catch specific exceptions.

try:
    with open("/etc/hostname") as f:
        content = f.read()
except FileNotFoundError:
    print("Hostname file missing")

8. File I/O: with open

The with statement manages file resources automatically — it closes the file even if an error occurs. Use "r" for read, "w" for write, "a" for append.

with open("servers.txt", "r") as f:
    for line in f:
        print(line.strip())

9. if __name__ == "__main__":

This guard ensures code only runs when the script is executed directly, not when imported. It’s a best practice for every script.

def main():
    print("Running main")

if __name__ == "__main__":
    main()

Hands-on walkthrough

Now let’s put it all together. We’ll write a script that reads a list of servers from a file, pings each (simulated), and logs the results.

Setup

Create a file servers.txt with:

web-01
web-02
db-01

Script: check_servers.py

import sys
import time

def simulate_ping(server):
    """Return True if server is reachable, False otherwise."""
    # In real life, you'd use subprocess or a library like ping3
    return server != "db-01"  # Pretend db-01 is down

def check_servers(file_path):
    """Read servers from file and check each."""
    results = []
    try:
        with open(file_path, "r") as f:
            servers = [line.strip() for line in f if line.strip()]
    except FileNotFoundError:
        print(f"Error: {file_path} not found")
        return

    for server in servers:
        start = time.time()
        ok = simulate_ping(server)
        elapsed = time.time() - start
        status = "OK" if ok else "DOWN"
        print(f"{server}: {status} ({elapsed:.2f}s)")
        results.append((server, status, elapsed))

    return results

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python check_servers.py <file>")
        sys.exit(1)
    check_servers(sys.argv[1])

Run it:

python check_servers.py servers.txt

Expected output:

web-01: OK (0.00s)
web-02: OK (0.00s)
db-01: DOWN (0.00s)

Pro tip: Use sys.argv to make your script reusable. Never hardcode file paths — accept them as arguments or environment variables.

Exercise: extend the script

Modify check_servers.py to read servers from a JSON file instead of a plain text file. Use a list of dicts: [{"name": "web-01", "port": 8080}]. Add a --timeout argument using argparse. You’ll practice dicts, loops, and error handling.

Compare options / when to choose what

For scripting, you’ll often choose between different constructs. Let’s compare common pairs.

for loop while loop
Use when Iterating over a known sequence (list, range, file lines) Repeating until a condition changes (e.g., retry with backoff)
Risk Infinite loop if you modify the sequence while iterating Infinite loop if condition never becomes false
Typical DevOps use Iterate over server lists, config keys Retry until success or timeout
list tuple
Mutable? Yes (can add/remove/change items) No (immutable)
Use when You need to accumulate results or modify the collection You want a fixed sequence (e.g., coordinates, version numbers)
Example servers = [] then servers.append("web-01") version = (3, 10)
dict json module
Purpose In-memory key-value mapping Serialize/deserialize data to/from strings/files
Use when You have configuration or structured data in memory You need to read/write JSON config files
Example config["port"] json.load(f)

When to choose what?

  • Use f-strings over % formatting or .format() — they’re more readable and faster.
  • Use list comprehensions ([x for x in iterable if condition]) for simple transformations, but avoid them if they hurt readability.
  • Use with open over manual open()/close() — it’s safer and cleaner.
  • Use argparse over manual sys.argv parsing for scripts with more than one argument — it handles help, defaults, and validation.

Pro tip: If you find yourself writing for i in range(len(lst)):, you’re probably overcomplicating. Use for item in lst: or enumerate(lst) if you need the index.

Troubleshooting & edge cases

SyntaxError: expected an indented block

You forgot to indent after a colon. Always use 4 spaces (or a consistent tab, but mix them and you’ll get an error). Example:

if x > 0:
print("Positive")  # IndentationError

Fix: Add an indented block under the if.

NameError: name 'x' is not defined

You’re using a variable before it’s assigned, or you misspelled its name. Check spelling and order of statements.

TypeError: can only concatenate str (not "int") to str

You tried to concatenate a string with an integer. Use f-strings or str() conversion.

# Wrong
print("Port: " + 8080)
# Right
print(f"Port: {8080}")

UnicodeDecodeError when reading files

When reading text files, specify encoding: open(file, "r", encoding="utf-8"). This is especially important in DevOps where files may have non-ASCII characters.

Infinite loops

A while True: loop without a break will run forever. Always ensure the condition can become false or include a break.

Modifying a list while iterating

If you remove items from a list during iteration, you’ll skip elements. Instead, iterate over a copy: for item in list(my_list):.

What you learned & what's next

You’ve now covered the core Python syntax for scripting: indentation, variables, data types, conditionals, loops, functions, f-strings, file I/O, error handling, and the __main__ guard. You also wrote a complete script that reads a file, processes a list, and logs results — a tiny version of the automation you’ll do every day.

Key takeaway: Python syntax is predictable. Once you internalize indentation and the basic data types, you can read and write scripts with confidence.

What’s next? In the next lesson, you’ll learn how to work with files and environment variables in scripts — a critical skill for making your automation portable and configurable. You’ll build on the file I/O you practiced here.

Practice recap

Practice recap: Extend the check_servers.py script to accept a --timeout flag using argparse, and have it read servers from a JSON file instead of a plain text file. Run it against a sample JSON file to confirm the output. Then, try to intentionally cause a TypeError and fix it using f-strings. This will cement the core syntax you just learned.

Common mistakes

  • Forgetting the colon after if, for, def, etc. — Python raises a SyntaxError.
  • Mixing tabs and spaces for indentation — causes an IndentationError or even a TabError.
  • Trying to concatenate a string and an integer without converting — use f-strings or str().
  • Using a variable outside its scope (e.g., defined inside a function and then accessed globally) — get a NameError.

Variations

  1. Use list comprehensions instead of for loops for simple transformations, e.g., [line.strip() for line in f].
  2. Use argparse instead of manual sys.argv parsing for scripts with multiple options — it generates help and handles validation.
  3. Prefer pathlib over os.path for file operations — Path objects are more intuitive and modern.

Real-world use cases

  • A deployment script that reads a list of target servers from a file and runs configuration commands on each using SSH.
  • A cron job that parses a log file, counts error occurrences, and sends an alert if the count exceeds a threshold.
  • A CI/CD helper script that checks the status of multiple microservices by calling their health endpoints and reports failures.

Key takeaways

  • Python's core syntax is built on indentation (4 spaces) and data types — master these to write clean scripts.
  • Use if/elif/else for conditionals and for/while for loops to control the flow of your automation.
  • Define reusable logic with def functions and guard the entry point with if __name__ == "__main__":.
  • Leverage f-strings for readable string interpolation and with open for safe file I/O.
  • Use try/except to handle errors gracefully — a script that doesn't crash mid-run is a reliable script.
  • Always test your script with small sample data before running it against production systems.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.