Cyber Town; training data next 100 miles

ICTPRG435 Write scripts for software applications

ICTPRG43540 nominal hoursIn progressUpdated 3 September 2026

The unit as writtenunit scope

This folded block is the official scope, kept out of the way of the notes. ICTPRG435 is a nationally recognised unit from the ICT Information and Communications Technology Training Package, Release 1, released 18 December 2024 (training.gov.au, unit page and the ICTPRG435_R1 release document, read 24 August 2026). It is delivered as an elective inside 22603VIC Certificate IV in Cyber Security, where its nominal duration is 40 hours; the nominal hours come from the CDU TAFE course document for 22603VIC held in the vault, since national units do not themselves carry nominal hours. There are no prerequisites and no licensing or legislative requirements attached to the unit.

What the unit is about. The unit covers the skills and knowledge required to plan, design and build scripts, using a scripting language, to create interactive and automated software applications. The training package names the target roles as application developers, application-support staff, programmers specialising in a scripting language, web application programmers and web developers. In a cyber security course the same skill is the one that lets a technician automate the repetitive, parse a log, call an API, glue two tools together and stop doing by hand what a machine should do.

What a student is expected to be able to do. The unit is written as four elements. Specify the software application requirements: identify the required outcomes and confirm expectations with the relevant people. Determine the script requirements: identify the characteristics of the scripting language, choose an integrated development environment, and identify the protocols and object models the language uses. Design and build the scripts: write pseudo code that describes the logic, review and amend it, translate it into a script using the basic elements of the language, and apply item-manipulation techniques. Finalise the scripts: write internal documentation to organisational procedures, review and debug, then save, confirm and hand the work back to the relevant people.

Foundation skills. Beyond the technical elements the unit calls out reading (comprehending requirements and technical documentation, and reading scripting texts and pseudo code critically), oral communication (listening and questioning to confirm requirements in the right industry terms), writing (documenting scripts with appropriate vocabulary and conventions), planning and organising (choosing a framework and IDE that suit the purpose and its limits) and problem solving (systematically working through the logic of a script).

Performance and knowledge evidence. To be assessed as competent a student must design, write and integrate at least one script into a software solution that meets stated requirements, test and debug that script, and use a required framework and an integrated development environment while building it. The knowledge behind that includes software development platforms; the organisational and legislative requirements that apply to writing scripts; the software development life cycle and its phases; the integrated development environment; the features and functions of scripting languages; and the processes and techniques used to build small applications.

Assessment conditions. Skills must be demonstrated in a workplace or in a simulated workplace or industry environment, with access to the hardware, the scripting language and its framework, an integrated development environment, and the organisational documentation and procedures a real task would involve. Assessors must meet the assessor requirements set out in the applicable vocational education and training standards.

A note on how these notes treat the scope. The unit is deliberately language-neutral; it will accept any reasonable scripting language. These notes teach it through Python, because Python is the language a cyber security technician will reach for most often, and they show the same ideas briefly in PowerShell and Bash so the transferable pattern is visible. Where the notes go past the bare syllabus, into secure coding, version control and using an AI assistant well, that is on purpose; those are the parts of real scripting work the 2024 unit describes only in outline.

What this unit is really about

Scripting is the craft of telling a computer to do, in order and without you, the small jobs you would otherwise do by hand. A script is a set of instructions in a language the machine can read directly; you write it in plain text, the interpreter reads it top to bottom, and the work happens. That is the whole idea, and it is why scripting is often the first properly useful programming a person learns.

The distinction the unit leans on is between a scripting language and a full systems programming language. A scripting language is usually interpreted rather than compiled, forgiving about types, quick to write, and built for gluing existing tools and data together rather than for building an operating system. You trade a little raw speed for a great deal of speed in getting something working. For most automation, most data wrangling and most of the tasks a cyber technician meets, that is exactly the right trade.

Why does this belong in a cyber security qualification? Because so much of security work is volume. Thousands of log lines, hundreds of hosts, a folder of files to hash, an API that will tell you whether an address is known-bad if only you ask it a thousand times. A person cannot keep up; a script can. The technician who can write twenty lines of Python to answer a question the tools do not answer out of the box is worth far more than one who waits for a vendor to add a button. This unit is where that begins.

Did you know that the word "bug", for a fault in a program, is often traced to a real moth found stuck in a relay of the Harvard Mark II in 1947, taped into the logbook with the note "first actual case of bug being found"? The story is charming and slightly tidied up, since engineers used "bug" for faults well before that, but the habit it points to is the real lesson of this unit: writing the script is half the job, and finding out why it does not work is the other half.

Scripting versus programming: what a scripting language actually is

It helps to fix a few properties early, because the unit's knowledge evidence asks for "the features and functions of scripting languages" and these are they.

Interpreted: the code runs through an interpreter that reads and executes it line by line, rather than being compiled ahead of time into a standalone machine-code program. You can run a script the instant you have written it, with no separate build step.

Dynamically typed: you do not declare in advance that a variable holds a whole number or a piece of text; the interpreter works it out at run time from what you put in it. This is quicker to write and easier to get wrong in subtle ways, which is why testing matters.

High level: the language hides the machine's detail, its memory addresses and registers, behind readable words and structures, so you spend your attention on the problem rather than the plumbing.

Glue: scripting languages are strong at joining things, a file to a web request, one program's output to another's input, a spreadsheet to a database, which is most of what real automation is.

A cyber security technician meets three scripting languages often enough to know them apart. Python is the general-purpose favourite, readable, huge in its library support, and the default for security tooling, data work and automation. PowerShell is Microsoft's automation shell and language, the natural choice for anything on Windows or in a Microsoft cloud, and the one the Windows security unit leans on. Bash is the shell scripting language of Linux and macOS, the glue that ties command-line tools together on those systems. These notes teach Python and show the other two in passing; the concepts, variables, decisions, loops, functions, are shared, so learning one well makes the next far quicker.

Setting up: the interpreter and the IDE

The unit asks you to identify and use an integrated development environment, so it is worth being deliberate about the setup rather than treating it as a preliminary to rush past.

Two pieces do the work. The interpreter is the program that runs your Python; on Windows you install it from python.org or the Microsoft Store, on macOS and Linux a version is usually present already, and you confirm it from a terminal with python --version. The integrated development environment, or IDE, is where you write the code: an editor that understands the language, highlights your syntax, suggests completions, flags obvious errors before you run, and gives you a debugger. Visual Studio Code with the Python extension is the common free choice and the one these notes assume; PyCharm is a heavier, Python-specific alternative, and IDLE ships with Python itself for a first look.

Two habits are worth forming from the start. The first is the interactive prompt, the REPL, reached by typing python on its own. It reads a line, evaluates it, prints the result and loops, hence the name, and it is the fastest way to test an idea or check what a piece of code does without writing a whole file. The second is the virtual environment. A virtual environment is a private, per-project copy of Python and its installed packages, so that the libraries one project needs cannot collide with another's:

# create a virtual environment in a folder called .venv
python -m venv .venv

# activate it (Windows PowerShell)
.venv\Scripts\Activate.ps1

# activate it (macOS or Linux)
source .venv/bin/activate

# now packages you install belong to this project only
pip install requests

Getting into the habit of a fresh virtual environment per project saves the classic beginner's afternoon lost to two projects fighting over incompatible versions of the same library.

The software development life cycle for a single script

Elements 1 and 4 of the unit, specifying requirements at the start and finalising properly at the end, are really the unit insisting that even a small script follows the software development life cycle. The life cycle is just the ordered phases a piece of software passes through, and shrinking it to fit a twenty-line script does not remove any phase; it only makes each one shorter.

flowchart LR
  R["Requirements:\nwhat must it do?"] --> D["Design:\npseudo code the logic"]
  D --> B["Build:\nwrite the script"]
  B --> T["Test and debug:\ndoes it do it?"]
  T --> Doc["Document and finalise"]
  Doc --> M["Maintain:\nchange it later"]
  T -->|faults found| B

The phase students most want to skip is the first. It is tempting to open the editor and start typing, but a script written before you can say plainly what "done" looks like tends to solve the wrong problem neatly. Specifying the requirement is often one sentence: "read yesterday's web server log and list the ten addresses that made the most requests". Confirming it with the person who asked, the unit's "discuss expectations with relevant personnel", is what stops you building the wrong ten. The last phase, finalising, is the one students skip once the thing works: documenting it, cleaning it up, saving it where it belongs and telling the person it is ready. The unit marks both ends deliberately because both are where real scripts go wrong in practice, not in the middle where the code is.

From requirement to pseudo code

The unit's Element 3 asks for pseudo code before code, and it is worth taking seriously rather than treating as a hoop. Pseudo code is a plain-language sketch of the logic, written in structured English rather than in any particular language, so you can get the thinking right before the syntax gets in the way. It reads like a recipe:

open the log file
set up an empty tally of addresses
for each line in the file:
    pull out the address at the start of the line
    add one to that address's count in the tally
sort the tally from highest count to lowest
print the top ten addresses and their counts
close the file

Notice what the pseudo code has done. It has forced the phases into order, exposed a question you would otherwise hit mid-code (what counts as "the address"?), and given you a checklist to translate one line at a time. Reviewing and amending the pseudo code, which the unit lists as its own performance criterion, is cheaper here than reviewing and amending finished code; changing a line of English costs seconds, changing a tangled function costs an afternoon. Only once the sketch reads correctly do you translate it, step by step, into the language.

The building blocks: variables, data types and expressions

Every script is built from a small set of pieces, and Python's are typical of scripting languages. A variable is a name that holds a value; you make one just by assigning to it. A data type is the kind of value held, and the interpreter tracks it for you.

# text is a string
username = "s.davis"

# whole numbers are integers
failed_attempts = 3

# numbers with a decimal point are floats
risk_score = 7.5

# true or false values are booleans
is_locked = False

# a string can be built from other values
message = f"Account {username} has {failed_attempts} failed attempts"
print(message)
# Account s.davis has 3 failed attempts

The four basic types above, string, integer, float and boolean, cover most single values you will handle. Expressions combine them: arithmetic on numbers (+ - * / %, where % is the remainder), comparison to produce a boolean (== equal, != not equal, <, >, <=, >=), and joining or formatting strings. The f-string in the example, a string with an f before the opening quote and values in braces, is the modern, readable way to build text from values, and you will use it constantly for building messages, file paths and log lines.

One property of a scripting language shows itself here. Because Python is dynamically typed, nothing stopped you assigning a string to a variable that held a number a moment ago, and that flexibility is a convenience and a trap in equal measure. A value read from a file arrives as text even when it looks like a number, so "3" + "4" is the string "34", not 7; converting explicitly with int() or str() when you cross that boundary is one of the most common fixes a beginner learns to reach for.

Control flow: making decisions and repeating work

A script that runs straight down the page, doing the same thing every time, is barely more than a list. The power comes from two structures: choosing between paths, and repeating work. These are shared by every language in the unit's scope, so the pattern matters more than the punctuation.

Choosing is done with if, elif (else-if) and else. The script tests a condition, and runs the indented block belonging to the first condition that is true:

risk_score = 7.5

if risk_score >= 8:
    print("Critical: escalate now")
elif risk_score >= 5:
    print("Elevated: investigate today")
else:
    print("Routine: log and move on")
# Elevated: investigate today

Python marks which lines belong to a block by indentation rather than by brackets, so the spaces are part of the meaning, not decoration. Getting the indentation right is getting the logic right.

Repeating is done with loops. A for loop walks through a collection of items, one at a time; a while loop keeps going as long as a condition holds:

addresses = ["10.0.0.5", "10.0.0.9", "10.0.0.5"]

# a for loop handles each item in turn
for address in addresses:
    print(f"Checking {address}")

# a while loop repeats until a condition changes
attempts = 0
while attempts < 3:
    print(f"Attempt {attempts}")
    attempts = attempts + 1

The choice between them is simple in practice: use for when you know the set of things to work through, which is most of the time, and while when you must keep going until something changes and you cannot say in advance how many rounds that will take. The trap unique to while is the loop whose condition never becomes false, which runs forever; making sure something inside the loop changes the tested value, as attempts does above, is how you avoid it.

Collections and item manipulation

The unit's Element 3 lists "item manipulation techniques", and in a scripting language that means working with collections: values that hold many other values. Two collections carry most of the load.

A list is an ordered sequence you can index, slice, add to and sort. A dictionary is a set of key-and-value pairs, a lookup table, where you fetch a value by its key rather than by position. Between them they model most data a script handles.

# a list: ordered, indexed from zero
ports = [22, 80, 443, 3389]
ports.append(8080)          # add to the end
print(ports[0])             # first item: 22
print(ports[-1])            # last item: 8080
print(ports[1:3])           # a slice: [80, 443]
print(sorted(ports))        # a sorted copy

# a dictionary: look values up by key
service = {22: "SSH", 80: "HTTP", 443: "HTTPS"}
print(service[443])         # HTTPS
service[3389] = "RDP"       # add a new pair
for number, name in service.items():
    print(f"Port {number} is {name}")

Slicing, shown above as ports[1:3], is a scripting convenience worth internalising: it takes a section of a sequence by start and stop position, and it works the same way on strings, so "failed"[0:4] is "fail". Iterating over a dictionary with .items() to get each key and value together is the everyday pattern for tallying and reporting, which is exactly what the worked example later in these notes does with it.

Two more collections round out the set and are worth recognising even if you use them less. A tuple is like a list but fixed once made, used for values that belong together and should not change, such as a coordinate or a host-and-port pair. A set is an unordered collection with no duplicates, which makes it the quick way to answer "how many distinct addresses appeared?": put them in a set and ask its length.

Functions: naming and reusing your logic

As a script grows, the same few lines start to repeat, and repetition is where bugs breed, because a fix has to be made in every copy. A function is a named, reusable block of logic: you define it once, give it inputs, and call it by name wherever you need it.

def is_strong_password(password):
    """Return True if the password meets a basic length and variety rule."""
    if len(password) < 12:
        return False
    has_digit = any(character.isdigit() for character in password)
    has_letter = any(character.isalpha() for character in password)
    return has_digit and has_letter

# call it as often as you like, from anywhere
print(is_strong_password("short"))            # False
print(is_strong_password("correcthorse7"))    # True

The function above has the three parts every function has: a name that says what it does, parameters that take its input (password), and a return value that hands an answer back to whoever called it. The single most valuable habit a beginner can form is to notice when a block of code is doing one identifiable job and to lift it into a well-named function. It shortens the main script, makes each piece testable on its own, and turns the program from a wall of instructions into a short list of named steps that reads almost like the pseudo code you started from. The principle has a name worth carrying: do not repeat yourself.

The triple-quoted line just inside the function is a docstring, a built-in place to say what the function does; it is the unit's "internal documentation" done in the tidiest possible way, and tools and the IDE will show it back to you when you use the function later.

Working with files and data

Most useful scripts read something in or write something out, and the unit's automation focus makes file work central. Reading a text file in Python is done with open, and the with form is the one to learn because it closes the file for you even if something goes wrong partway:

# read a file line by line and count the lines
line_count = 0
with open("auth.log", "r", encoding="utf-8") as log_file:
    for line in log_file:
        line_count = line_count + 1
print(f"The log has {line_count} lines")

# write a report out to a new file
with open("report.txt", "w", encoding="utf-8") as report:
    report.write("Daily summary\n")
    report.write(f"Lines processed: {line_count}\n")

The "r" opens for reading and "w" for writing (which replaces the file; "a" appends instead). Setting encoding="utf-8" explicitly saves you from a common and confusing class of errors when a file contains characters outside the plain English set.

Two structured formats appear so often that Python builds them in. CSV, comma-separated values, is the lingua franca of spreadsheets and exported logs, handled by the csv module. JSON, JavaScript Object Notation, is the format almost every web API speaks, and the json module turns it into Python dictionaries and lists and back again with a single call each way. Reaching for these modules rather than trying to split text by hand is the difference between a script that works and one that breaks on the first value containing a comma.

Reaching the outside: modules, libraries and APIs

No script is written entirely from scratch, and the unit's Element 2, identifying the protocols and object models a language offers, is really about knowing what the language already gives you and how to pull in more.

Python's standard library is the large set of modules that ship with the interpreter; you make one available with import. Beyond it sits the Python Package Index, the public repository of hundreds of thousands of third-party libraries, installed with pip into your virtual environment. The skill is knowing that a problem is almost certainly solved already, and searching before writing.

import hashlib          # from the standard library, no install needed
import requests         # third-party: pip install requests first

# hash a file's contents (useful for checking integrity)
with open("sample.bin", "rb") as f:
    digest = hashlib.sha256(f.read()).hexdigest()
print(digest)

# ask a web API a question and read its JSON answer
response = requests.get("https://api.github.com/zen")
print(response.status_code)   # 200 means the request succeeded
print(response.text)

The second half of that example is an application programming interface, an API, in miniature. An API is the agreed way one program asks another for data or action; a web API is reached over the same HTTP protocol a browser uses, you send a request to a web address and read a structured reply, usually JSON. This is the object-model-and-protocol idea the unit names, made concrete: the requests library gives you a small set of objects and methods that hide the protocol's detail, so you write requests.get(...) and read response.status_code rather than hand-crafting network packets. For a cyber technician this one pattern, call an API, read the JSON, act on it, unlocks threat-intelligence lookups, ticketing systems, cloud platforms and most of the tooling worth automating.

Handling errors and the unexpected

A script that assumes everything will go right is a script that stops dead the first time a file is missing or a network call times out. The unit's testing-and-debugging outcome starts here, with writing code that expects trouble.

Python signals a problem by raising an exception, an error object that stops the program unless you catch it. You catch it with try and except: the code that might fail goes in the try block, and what to do when it does goes in the except:

def read_config(path):
    try:
        with open(path, "r", encoding="utf-8") as config_file:
            return config_file.read()
    except FileNotFoundError:
        print(f"No config at {path}; using defaults")
        return ""
    except PermissionError:
        print(f"Not allowed to read {path}")
        return ""

settings = read_config("missing.conf")
# No config at missing.conf; using defaults

Catching specific exceptions by name, FileNotFoundError rather than a blanket catch-all, is what separates a script that handles a known problem from one that silently swallows every error including the ones you needed to see. The related habit is validating input before you trust it: checking that a value the script was given is the right shape, in range, and present, rather than assuming it. For anyone heading into security this is doubly important, because unvalidated input is the root of a large share of vulnerabilities, and a script you write is software that can be attacked like any other.

Testing and debugging

The unit lists debugging as a performance criterion, and it is a skill in its own right, not a sign that you wrote the code badly. Every programmer debugs; the good ones are simply quicker and calmer about it.

Start with reading the error. When Python stops, it prints a traceback: the chain of calls that led to the failure, ending with the line that broke and the type of exception. The instinct to skim past it is the wrong one; the traceback usually names the file, the line and the reason, and reading it from the bottom up answers most questions before you have touched the code.

Three techniques cover most debugging. The oldest is the print statement: drop a print() in to show a value at a chosen point, run it, and see whether the value is what you expected; it is crude and it is effective. The IDE's debugger is the grown-up version: you set a breakpoint on a line, the program pauses there, and you inspect every variable and step forward one line at a time, watching the state change. The third is the assertion, a line that states what must be true at a point and stops the program with a clear message if it is not:

def average(numbers):
    assert len(numbers) > 0, "average() needs at least one number"
    return sum(numbers) / len(numbers)

Beyond fixing faults as they appear, testing means checking on purpose that the code does what it should, including at the awkward edges: the empty file, the value of zero, the input that is too long, the network that is down. Writing a few small tests that feed a function known inputs and check its outputs, by hand at first and with a framework such as pytest later, is how you find the fault before the user does. The rule of thumb worth keeping is that the interesting bugs live at the boundaries, so test the empty case, the single case and the huge case, not just the comfortable middle.

Internal documentation and finalising the work

Element 4 asks you to document, review, debug, then save and confirm, and the documentation half is the one students undervalue until the day they reopen their own script six months later and cannot tell what it does. Internal documentation is the explanation that lives inside the code, for the next person to read, and the next person is often you.

Three things do most of the work. Comments, lines beginning with #, explain why a piece of code exists where the code itself already shows what it does; a good comment says "skip the header row" rather than restating the obvious. Docstrings, the triple-quoted descriptions inside functions shown earlier, document what a function is for, what it takes and what it returns. And names carry more documentation than any comment: a variable called failed_login_count needs no explanation, where one called x needs a sentence. The unit's "organisational procedures" point is that workplaces usually have a house style for all of this, and matching it is part of finishing the job.

Finalising also means version control, which the 2024 unit gestures at through its software-development-platform knowledge and which real work assumes. Git is the near-universal tool: it records the history of your changes, lets you go back to a version that worked, and lets more than one person work on the same code without overwriting each other. Even for a solo script, committing your work to Git as you reach each working point turns "I broke it and cannot get back" into a two-command recovery. Saving the finished script where the team keeps its code, and confirming with the person who asked that it does what they needed, is the unit's last performance criterion and the difference between a script that helped once and one the team can rely on.

A worked example, end to end

To tie the phases together, here is a small, safe task carried through the whole life cycle. The requirement, in one sentence confirmed with the person who asked: read a web server access log and report the ten addresses that made the most requests, so we can see who is hammering the site. The pseudo code is the sketch shown earlier in these notes. The build translates it, one step at a time, into a script that uses a variable, a loop, a dictionary, a function, file handling and error handling, every building block from the sections above:

from collections import Counter

def top_addresses(log_path, how_many=10):
    """Return the most frequent source addresses in an access log."""
    counts = Counter()
    try:
        with open(log_path, "r", encoding="utf-8") as log_file:
            for line in log_file:
                line = line.strip()
                if not line:
                    continue                 # skip blank lines
                address = line.split()[0]    # address is the first field
                counts[address] += 1
    except FileNotFoundError:
        print(f"No log found at {log_path}")
        return []
    return counts.most_common(how_many)

# run it and print a small report
for address, hits in top_addresses("access.log"):
    print(f"{address:<16} {hits} requests")

The script reads cleanly because the logic was sorted out in pseudo code first, the counting job is lifted into a named function, and Counter (a specialised dictionary from the standard library) does the tallying that would otherwise be a handful of lines. Testing it means feeding it a small log with known contents and checking the numbers, then trying the awkward cases: a file that is not there (handled), a blank line (skipped), a malformed line with no fields (which would raise an error on line.split()[0], and is the next thing to harden). Documenting it means the docstring, a comment on the two non-obvious lines, and clear names. Finalising it means saving it to the team's scripts folder, committing it to Git, and telling the person it is ready. That is the unit, in one page of code.

Security when you are the one writing the script

This is a cyber security course, so a section the base unit only implies earns its place: a script is software, and software you write can be insecure. A handful of habits keep your own scripts from becoming the weak point.

Never hard-code secrets. An API key, a password or a token written into the script is a secret published to everyone who can read the file, and to everyone it is ever shared with or committed to Git. Read secrets from an environment variable or a separate configuration file that is kept out of version control. Validate and distrust input, especially anything from a file, a user or the network; the script should decide what a valid value looks like and reject the rest, rather than passing whatever it is given straight into a command or a query. Avoid the dangerous shortcuts: functions that run arbitrary text as code, such as eval, or that hand a string straight to the operating system shell, are how a helpful script becomes a way in. Run with the least privilege the task needs, not as an administrator by reflex. And treat your dependencies as part of your attack surface: every library you pip install is code you are trusting, so prefer well-known packages, check the name carefully (attackers publish look-alike packages hoping for a typo), and keep them updated. None of this is advanced; it is the same defensive mindset the rest of the course teaches, applied to the fact that you are now the author.

The other two shells, in brief

Because a cyber technician moves between systems, it is worth seeing the same idea in the other two languages the unit's scope allows, so the pattern reads as language-independent. The task is the same each time: greet a name and count to three.

# Python
name = "Sally"
print(f"Hello {name}")
for number in range(1, 4):
    print(number)
# PowerShell (Windows automation)
$name = "Sally"
Write-Output "Hello $name"
1..3 | ForEach-Object { Write-Output $_ }
# Bash (Linux and macOS shells)
name="Sally"
echo "Hello $name"
for number in 1 2 3; do
  echo "$number"
done

The punctuation differs, the ideas do not: a variable, a way to output text, and a loop over a small range. PowerShell is object-based, passing rich objects along the pipeline rather than plain text, which makes it powerful for Windows administration; Bash passes text between small, sharp command-line tools, which makes it the glue of Unix-like systems. Learning Python first and then reading either of these is far easier than meeting them cold, which is the argument for a language-neutral unit taught through one language well.

Using an AI assistant to write scripts

A section the 2024 unit could not have written, because the ground has moved since, and one that matters because it is changing how scripts get written as these notes are prepared. AI coding assistants, GitHub Copilot in the IDE, and general assistants such as Claude and ChatGPT, will now draft a script from a plain-language description, explain code you do not understand, and suggest a fix for an error you paste in. Used well they are a real accelerant, particularly for the boilerplate and the "how do I do this again" lookups that used to cost a beginner an hour.

The honest framing is the same one that applies to AI everywhere in this course. The assistant is fast and confident and sometimes wrong; it will produce code that looks right, runs, and does the wrong thing, or that carries a security weakness you would not have written yourself. It has no way to know your requirement beyond what you tell it, so it cannot judge whether its answer actually solves your problem. The skill the assistant does not replace is the one this unit teaches: reading a script and knowing whether it is correct, safe and doing what was asked. A student who can specify the requirement, sketch the logic, read the generated code critically, test it at the edges and take responsibility for the result gets the speed and keeps the judgement. A student who pastes a request and ships whatever comes back has automated their own mistakes. The point of learning to write scripts by hand, in an age when a machine will draft them, is precisely so you can tell a good draft from a dangerous one.

Building a safe place to practise

Scripting is learned by writing scripts, and the good news is that the barrier is almost nothing: Python and a free IDE, and a folder of small problems. Keep your practice on files and data you own or have made up, not on live systems or other people's data, and keep anything security-flavoured to a lab you control, the same isolated virtual-machine pattern the other units describe.

For structured practice, a few resources stand out and are current as at August 2026. The official Python tutorial at docs.python.org is the authoritative reference and a solid first read. Automate the Boring Stuff with Python, free to read online at automatetheboringstuff.com, teaches scripting through exactly the kind of small real tasks this unit is about. Exercism (exercism.org) and Codewars (codewars.com) give graded practice problems with feedback, and the Python track on either is a good structured path. For the security flavour, TryHackMe (tryhackme.com) has introductory Python-for-security and scripting rooms that put the skill straight to work on defensive tasks. The habit that turns any of these into real skill is the same one the unit is built around: take a small annoyance in your own work, something you do by hand and dislike, specify it in a sentence, sketch it in pseudo code, and write the twenty lines that make it go away. Do that a dozen times and the unit's outcomes are yours.

Sources used

These notes were built for personal professional development from current, authoritative sources rather than transcribed from the training package. The unit scope block draws on the training.gov.au page and release document for ICTPRG435 Write scripts for software applications, Release 1, released 18 December 2024, read 24 August 2026 (training.gov.au and the ICTPRG435_R1 release PDF) for the application, the four elements and their performance criteria, and the foundation skills (high confidence). The performance evidence, knowledge evidence and assessment conditions summary follows the Victoria University published unit page for ICTPRG435 (vu.edu.au, read 24 August 2026; no page-modified date shown) cross-checked against the training.gov.au wording (medium confidence, since the full evidence text on training.gov.au could not be retrieved directly and the VU page paraphrases it). The 40-hour nominal duration and the unit's placement as an elective in 22603VIC Certificate IV in Cyber Security follow the CDU TAFE course document for 22603VIC held in the vault, consistent with the value already recorded in this unit's front matter (medium confidence). The Python teaching content is grounded in the official Python documentation at docs.python.org (Python 3, current release), which is the authoritative reference for the language features, the standard-library modules (csv, json, hashlib, collections), and the syntax shown; the requests library is documented at requests.readthedocs.io. Practice references point to the projects' own sites: docs.python.org, automatetheboringstuff.com, exercism.org, codewars.com and tryhackme.com. All code examples in these notes were run and confirmed to work before publication.

Not fully confirmed: the exact training.gov.au wording of the performance evidence and knowledge evidence (retrieved via the Victoria University mirror rather than directly, as the training.gov.au evidence sections would not load through the fetch); and the 40-hour nominal duration, taken from the front matter and the course document rather than re-verified against a live source in this session.