
To get at the arguments passed to your script on the command line, you use sys.argv. This lives in the sys module, so you’ll have to import sys to use it. The interesting thing about sys.argv is how utterly simple it is. It isn’t some special data type with its own methods and protocols. It’s just a list. A regular Python list, filled with strings.
This means if you know how to work with lists, you know how to work with command line arguments. There’s nothing new to learn. Consider this tiny script; let’s call it args.py.
import sys
print(f"The type is: {type(sys.argv)}")
print(f"The contents are: {sys.argv}")
If you run this from your shell and pass it a few words, you can see what’s happening.
$ python args.py first_arg 2 another
The program will print this:
The type is: <class 'list'> The contents are: ['args.py', 'first_arg', '2', 'another']
As you can see, it really is a list. The first element, sys.argv[0], is the name of the script file itself. This is a convention inherited from the C programming language. The actual arguments you provided follow after that. So your first argument is at sys.argv[1], your second at sys.argv[2], and so on.
Since it’s a list, you can use standard list operations on it. The most common thing to do is check its length with len() to see if the user provided the expected number of arguments. This is fundamental for input validation.
import sys
# We need the script name plus at least one argument.
if len(sys.argv) < 2:
print("Error: You must supply a filename.")
# Use sys.argv[0] to show the user how to run the script.
print(f"Usage: python {sys.argv[0]} <filename>")
sys.exit(1) # Exit with a non-zero status code for error.
filename = sys.argv[1]
print(f"Processing file: {filename}")
This pattern is everywhere. You check the number of arguments, and if it’s wrong, you print a usage message and exit. The arguments themselves are accessed via their index. But there’s a catch, one that trips up beginners. Look at the output from our first example. Every single item in the list is a string. The number 2 we passed on the command line became the string '2' inside the list. This is a crucial detail. The shell doesn’t know about Python types; it just passes along sequences of characters.
Apple Watch Series 11 [GPS 42mm] Smartwatch with Rose Gold Aluminum Case with Light Blush Sport Band - S/M. Sleep Score, Fitness Tracker, Health Monitoring, Always-On Display, Water Resistant
Now retrieving the price.
(as of July 9, 2026 13:58 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)What you do with the strings
So it’s up to you, the programmer, to turn these strings into whatever data type you actually need. If you expect an integer, you must call int() on the string. If you expect a floating-point number, you use float(). If you don’t do this, you’ll get behavior that might surprise you. Take a script that’s supposed to add two numbers passed on the command line.
# add.py
import sys
# Assume user provides two arguments
# sys.argv[0] is 'add.py'
# sys.argv[1] is the first number
# sys.argv[2] is the second number
num1 = sys.argv[1]
num2 = sys.argv[2]
result = num1 + num2
print(f"The result of {num1} + {num2} is {result}")
If you run python add.py 10 5, you might expect the output to be 15. But it’s not. It’s ‘105’. The + operator, when used with two strings, performs concatenation, not addition. It just joins them together. This is a common mistake.
The correct way to write this script is to explicitly convert the string arguments to numbers before you try to do math with them.
# add_fixed.py
import sys
num1_str = sys.argv[1]
num2_str = sys.argv[2]
num1_int = int(num1_str)
num2_int = int(num2_str)
result = num1_int + num2_int
print(f"The result of {num1_int} + {num2_int} is {result}")
Now, running python add_fixed.py 10 5 gives you the expected output: The result of 10 + 5 is 15. This is better, but it’s still fragile. What happens if the user runs python add_fixed.py 10 five? The program will crash. The call to int('five') will raise a ValueError because the string ‘five’ cannot be parsed into an integer.
A robust program has to anticipate user error. The way to handle this in Python is with a try...except block. You try to do the conversion, and if it fails, you catch the exception and print a helpful error message instead of letting the program crash.
# add_robust.py
import sys
if len(sys.argv) != 3:
print("Error: Please provide exactly two numbers.")
print(f"Usage: python {sys.argv[0]} ")
sys.exit(1)
try:
num1 = int(sys.argv[1])
num2 = int(sys.argv[2])
except ValueError:
print("Error: Both arguments must be valid integers.")
sys.exit(1)
result = num1 + num2
print(f"The sum is: {result}")
This version is much more solid. It first checks if the right number of arguments was supplied. Then, it tries to convert them to integers inside a try block. If either conversion fails, the ValueError is caught, a clean error message is printed, and the program exits. This combination of checking len(sys.argv) and using try...except for type conversion is the standard pattern for handling raw command line arguments. You treat them as untrusted input, validate them, and only then proceed with your program’s main logic.
The same principle applies to any kind of argument. If an argument is supposed to be a filename, you might want to check if the file exists using functions from the os module. If an argument is a flag, like --verbose, you’d check for its presence in the list. For example, if '--verbose' in sys.argv:. The core idea remains: sys.argv gives you a list of strings, and what you do with those strings is up to you. You have to parse them. For anything more complex than a few positional arguments, this manual parsing can become tedious. You end up writing a lot of boilerplate code to handle different flags, optional arguments, and help messages. This is why most real-world programs don’t parse sys.argv manually.
