Python Central HubSign in

Automation and Scripting / Phase 6: Task Scheduling & Deployment

Using Arguments with argparse

Build CLI automation tools with argparse - flags, defaults, and help messages.

diagram what argparse does before your code runs mermaid
The parser is not just a way to read sys.argv -- it validates, converts and, when something is wrong, exits. That last part surprises people: a bad value does not raise an exception you can catch in the ordinary way, it prints usage and terminates with status 2.

Why argparse

It gives your scripts:

  • --help
  • typed arguments
  • clear usage patterns

Example

Python
import argparse
 
 
def build_parser():
    p = argparse.ArgumentParser(description="Example automation CLI")
    p.add_argument("--dry-run", action="store_true", help="Don’t change files")
    p.add_argument("--source", required=True, help="Source folder")
    return p
 
 
def main():
    args = build_parser().parse_args()
    print("source:", args.source)
    print("dry_run:", args.dry_run)
 
 
if __name__ == "__main__":
    main()

Why scripts need arguments

A script with the folder name written inside it has to be edited every time you use it on another folder. A script with arguments can be reused, scheduled with different settings, and run safely with --dry-run. argparse is the standard-library way to define them, and it gives you --help for free.

The three kinds of argument

  • Positional arguments are required and identified by position: add_argument("path").
  • Options start with dashes and usually have a default: add_argument("--limit", type=int, default=10).
  • Flags are options with no value. action="store_true" makes --dry-run a boolean that is False unless the flag is given.

Useful keywords: type= converts the value (int, float, Path), choices=[...] restricts it, default= sets the fallback, nargs="+" accepts one or more values, and help= feeds the --help output.

A realistic tool

This script takes a folder and an extension, and lists or deletes the matching files. Deletion is off unless you ask for it, which follows the dry-run pattern from the safety lesson.

Python
import argparse
from pathlib import Path
 
 
def build_parser() -> argparse.ArgumentParser:
    p = argparse.ArgumentParser(description="Find, and optionally delete, files by extension")
    p.add_argument("folder", type=Path, help="folder to search")
    p.add_argument("--ext", default=".tmp", help="extension to match (default: .tmp)")
    p.add_argument("--apply", action="store_true",
                   help="actually delete; without this flag it only prints")
    return p
 
 
def main(argv=None) -> int:
    args = build_parser().parse_args(argv)
    if not args.folder.is_dir():
        print(f"error: {args.folder} is not a folder")
        return 1
 
    matches = sorted(args.folder.rglob(f"*{args.ext}"))
    for path in matches:
        action = "deleting" if args.apply else "would delete"
        print(action, path)
        if args.apply:
            path.unlink()
    print(f"{len(matches)} file(s)")
    return 0
 
 
if __name__ == "__main__":
    raise SystemExit(main())

Run it as python argparse_cleanup.py ./demo --ext .log, and then with --apply once the output looks right. Two design points help you later. main accepts argv, so a test can call main(["./demo", "--ext", ".log"]) without touching the real command line. And it returns an exit code, which SystemExit passes to the operating system. Cron and Task Scheduler use that code to tell success (0) from failure.

Exit codes and errors

By convention, 0 means success and anything else means failure. Return non-zero when the job did not do its work, so a scheduler or a shell script (python job.py && next_step) can react. For a wrong argument, argparse prints the usage line and exits with 2 for you. Use parser.error("message") to report your own validation problems in the same style.

Combining with configuration

Give every option a sensible default and put secrets in environment variables, not in arguments. Arguments are visible to other users in the process list, so --password on a command line is a bad idea.

Common mistakes

  • Reading sys.argv by hand, then handling quoting, types, and help yourself.
  • ns.dry-run. The dash becomes an underscore: args.dry_run.
  • Making destructive behaviour the default. Require --apply for the dangerous path.
  • Forgetting type=. --limit 5 arrives as the string "5", and "5" + 1 raises TypeError.
  • A bad default of a mutable type, such as default=[] with append.

πŸ§ͺ Try It Yourself

Exercise 1 – List Files with os.listdir

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Exercise 2 – Join Paths with os.path.join

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Exercise 3 – Write and Read a File

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Was this page helpful?

Let us know how we did