Working with Command Line Arguments in Python

Command-line arguments allow a Python script to accept filenames, options and commands without editing source code. For a tiny throwaway script, sys.argv may be enough. For a reusable tool, argparse from the standard library offers help messages, typed values, option flags and subcommands with more predictable error handling.

A robust command-line interface also treats its inputs as untrusted. Validate paths and numeric ranges, avoid building shell commands from arguments, and do not place secret tokens in ordinary command-line parameters where process listings or shell histories may expose them.

Read raw arguments with sys.argv

sys.argv is a list of strings. The first item normally represents the script name or invocation path, so user-supplied values start at index one. Explicit length checks prevent IndexError.

import sys
if len(sys.argv) < 2:
    print("Usage: script.py NAME")
else:
    print(sys.argv[1])

Start with argparse for reusable scripts

ArgumentParser creates a help interface and reports many input errors automatically. It supports required positionals, optional flags and typed conversion.

import argparse
parser = argparse.ArgumentParser(description="Task demo")
parser.add_argument("name")
parser.add_argument("--count", type=int, default=1)
args = parser.parse_args()
print(args.name, args.count)

Boolean flags and defaults

action=’store_true’ creates a flag that is false unless supplied. Prefer explicit flags to manually searching sys.argv for strings, because parsing libraries handle help output and unknown option errors consistently.

parser.add_argument("--verbose", action="store_true")
# parser.parse_args() returns a namespace with verbose

Input validation after parsing

Type conversion alone does not prove that a value is acceptable. A timeout may need to be positive and a path may need to belong to an allowed directory. Reject invalid values before touching files or networks.

parser.add_argument("--timeout", type=float, default=3.0)
args = parser.parse_args()
if args.timeout <= 0:
    parser.error("--timeout must be positive")

Build subcommands with subparsers

A CLI with distinct actions can use subparsers to organize required inputs. Keep operations narrow and document their effects.

parser = argparse.ArgumentParser()
sub = parser.add_subparsers(dest="command", required=True)
show = sub.add_parser("show")
show.add_argument("item")
args = parser.parse_args()

getopt and third-party parsers

The standard-library getopt module supports traditional option parsing, but its interface is lower level. Third-party docopt-style parsers can express usage-driven interfaces yet require dependency review. For most new Python tools, argparse is a maintainable default.

import getopt
options, rest = getopt.getopt(["-v", "file.txt"], "v")
print(options, rest)

Handle paths, encoding and errors

For file-oriented commands, use pathlib and explicit text encodings. Catch known exceptions such as FileNotFoundError and PermissionError, and return meaningful exit codes. Avoid broad except blocks that silently hide failures.

from pathlib import Path
path = Path("items.txt")
try:
    print(path.read_text(encoding="utf-8"))
except FileNotFoundError:
    print("File not found")

Avoid shell injection and secret leakage

Do not concatenate user arguments into a shell command string. For authorized subprocess execution, pass a list of arguments with shell=False by default. Use protected configuration or credential stores for secrets rather than public process command lines.

import subprocess
subprocess.run(["python", "--version"], check=True)
# Avoid shell=True with untrusted text

Conclusion

Use sys.argv for understanding the mechanics, argparse for most maintained command-line tools, and carefully selected alternatives only when justified. A good CLI is discoverable, validates input, reports failures and protects paths and credentials.

  • img