Command-line arguments with sys.argv

sys · Essentials · 7 min

Even tiny scripts become reusable once they take file names or options from the command line.

When you run python greet.py Ann --loud, Python stores the command line in sys.argv, a list of strings:

  • sys.argv[0] is the script name as given ('greet.py'), or '-c' when running python -c, or the full path of the module with python -m.
  • sys.argv[1:] are the arguments, always as strings, split by the shell: quoting "New York" keeps the space inside one argument.

Everything arrives as text, so convert explicitly: int(sys.argv[2]). Check the length before indexing, or you get an IndexError when the user forgets an argument; print a usage message to stderr and exit with a non-zero code instead.

For anything beyond one or two positional arguments, such as options, defaults, --help and type checking, use argparse, which reads sys.argv[1:] for you. Writing your own option parser over sys.argv is a common source of bugs.

A useful pattern is to pass the argument list into main(argv) instead of reading sys.argv inside your logic. Tests can then call main(["a.txt", "-n", "3"]) directly without touching global state.

sys.orig_argv (3.10+) holds the full original command line including interpreter options like -X dev.

Example

import subprocess
import sys

script = '''
import sys
def main(argv):
    if len(argv) < 1:
        print("usage: greet NAME [TIMES]", file=sys.stderr)
        return 2
    name = argv[0]
    times = int(argv[1]) if len(argv) > 1 else 1
    print(" ".join([f"hi {name}"] * times))
    return 0
sys.exit(main(sys.argv[1:]))
'''
open("greet.py", "w").write(script)
run = lambda *a: subprocess.run([sys.executable, "greet.py", *a],
                                capture_output=True, text=True)
print(run("Ann", "2").stdout.strip())   # hi Ann hi Ann
print(run("New York").stdout.strip())   # hi New York
print(run().returncode)                 # 2

Remember

  • sys.argv[0] is the script; sys.argv[1:] are the arguments, all strings
  • Validate the count and convert types yourself, or use argparse
  • Pass sys.argv[1:] into main(argv) so the logic is testable

Watch out for

  • Indexing sys.argv[1] without checking the length; a missing argument crashes with IndexError instead of a usage message.

Check yourself

  1. For the command python tool.py 3 4, what is sys.argv[1] + sys.argv[2]?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.python.org/3/library/sys.html#sys.argv

Builds on

Nothing: this is a foundation.

Unlocks

Nothing builds on this yet.