A Python file can be imported (used as a module by other code) or run (executed as a script). This lesson covers how to write files that do both, and how to pass them arguments from the command line.
The if __name__ == "__main__": pattern (recap)
You saw this in the modules lesson. Every Python file has a hidden variable __name__:
- When the file is run directly:
__name__ == "__main__" - When it’s imported:
__name__is the module’s name (e.g."greetings")
The standard pattern for a runnable module:
def main() -> None:
print("Doing the thing...")
if __name__ == "__main__":
main()
When run directly, main() runs. When imported, the file’s functions become available but main() doesn’t run automatically.
Running with python -m
There are two ways to run a Python file:
uv run python path/to/file.py
uv run python -m path.to.module
The first treats the file as a standalone script. The second treats it as a module inside a package. The difference matters when the file uses relative imports — only -m makes those work.
For example, given:
my_project/
└── tools/
├── __init__.py
└── analyse.py
Run it as:
uv run python -m tools.analyse
Not as python tools/analyse.py — that would break any relative imports inside.
Command-line arguments — sys.argv
When you run a script, Python passes any extra command-line arguments into a list called sys.argv:
import sys
print(sys.argv)
uv run python hello.py Manikandan 30
['hello.py', 'Manikandan', '30']
sys.argv[0] is the script name; the rest are the arguments. They’re always strings — convert if you need numbers.
A simple example:
import sys
def main() -> None:
if len(sys.argv) < 2:
print("Usage: python greet.py <name>")
sys.exit(1)
name: str = sys.argv[1]
print(f"Hello, {name}!")
if __name__ == "__main__":
main()
sys.exit(code) ends the program. 0 means success; anything non-zero means an error.
A nicer CLI — argparse
For anything beyond one or two arguments, sys.argv gets clunky. The standard library has argparse:
import argparse
def main() -> None:
parser = argparse.ArgumentParser(description="Greet someone")
parser.add_argument("name", help="The person's name")
parser.add_argument("--shout", action="store_true", help="Shout the greeting")
parser.add_argument("--times", type=int, default=1, help="How many times")
args = parser.parse_args()
message: str = f"Hello, {args.name}!"
if args.shout:
message = message.upper()
for _ in range(args.times):
print(message)
if __name__ == "__main__":
main()
Run it:
uv run python greet.py Manikandan --shout --times 3
HELLO, MANIKANDAN!
HELLO, MANIKANDAN!
HELLO, MANIKANDAN!
You also get a free --help:
uv run python greet.py --help
usage: greet.py [-h] [--shout] [--times TIMES] name
Greet someone
positional arguments:
name The person's name
options:
-h, --help show this help message and exit
--shout Shout the greeting
--times TIMES How many times
argparse is part of the standard library — no install needed. For fancier CLI tools, look at typer or click (third-party).
Standard input — sys.stdin
If you want your script to accept data piped in from another program:
import sys
for line in sys.stdin:
print(line.rstrip().upper())
Run it:
echo "hello world" | uv run python upper.py
HELLO WORLD
This is how the classic Unix tools (grep, awk, sort) are composed — by piping output of one into input of the next.
Exit codes
By default, a script exits with code 0 (success). To signal failure, call sys.exit(non_zero_int):
if not data:
print("No data found", file=sys.stderr)
sys.exit(1)
CI systems, shell scripts, and other tools use these codes to decide what happened. Use them properly in scripts that other systems run.
Summary of Section 11
You can now:
- Import modules (and rename them with
as) - Write your own modules that other files can import
- Organise modules into packages with
__init__.py - Recognise common standard library modules
- Build runnable scripts with
if __name__ == "__main__": - Pass command-line arguments with
sys.argvorargparse
These are the skills for growing a project from one file to many — without losing your way.
What’s next
Section 12: Object-Oriented Programming — defining your own types with classes and objects.