How to Run a Python Script: REPL, python -m and Main Guard
Run Python as a REPL, a script, a module with python -m or a one-liner with -c. What the main guard does, how exit codes work, and which flags help.
- Course: Python study plan
- Module: Python and the interpreter
- Kind: Lesson
- Reading time: 12 min
- Runtime: CPython 3.11
What does if __name__ == "__main__": do in Python?
The main guard, if __name__ == "__main__":, runs the code under it only when the file is executed directly as the program, not when it is imported. The interpreter sets a running script's __name__ to "__main__" and an imported module's to its module name, so one file can be a script and also a module whose functions a test imports without reading input or printing.
Lesson
There are four ways to hand code to the interpreter, and knowing which one you are in explains a whole class of "it works here but not there" confusions: the REPL, a script file, a module run with -m, and a one-liner with -c. This lesson walks through each, fixes the if __name__ == "__main__": idiom that every serious script uses, explains exit codes, and describes exactly how the study judge runs the programs you write in this track.
The REPL
Type python (or python3 on systems where python is still Python 2) with no arguments and you get the read–eval–print loop:
$ python
Python 3.11.13 (main) [GCC 13.3.0] on linux
>>> 2 ** 10
1024
>>> name = "Ada"
>>> f"Hello, {name}"
'Hello, Ada'
>>> _
'Hello, Ada'
The REPL evaluates each line and prints the value of an expression automatically, using repr — which is why the string comes back with quotes. _ holds the last printed value. Statements (name = "Ada") print nothing. The REPL is where you check what a method does or what an expression is before committing it to a file; help(str.split) and dir(str) answer most questions faster than a search. Leave with exit() or Ctrl-D.
Scripts
A script is a file run top to bottom:
$ python greet.py
# greet.py
name = "Ada"
print(f"Hello, {name}")
Nothing is printed unless you print it — the REPL's automatic echo is a REPL feature. The interpreter compiles the whole file first (a syntax error on any line stops everything), then executes statements in order. A def or class statement defines a function or class when it is reached; the body runs only when called. This is why a script that calls a function before its def fails with NameError: at the time of the call, the name has not been bound yet.
Modules and -m
Every Python file is a module; importing it runs its top-level code once and binds its names. python -m package.module runs a module as a script by its import name rather than its file path, which is how the standard library's tools are invoked:
$ python -m json.tool data.json # pretty-print JSON
$ python -m http.server 8000 # serve the current directory
$ python -m venv .venv # create a virtual environment
$ python -m pip install requests # pip for *this* interpreter
The -m form finds the module on the import path and sets things up as if it were the main script, which matters for packages with relative imports (Module 12). python -c "print(2 ** 64)" runs a one-liner; python -i script.py runs the script and then drops into the REPL with its names still defined — the quickest way to poke at a program's state.
__name__ and the main guard
When a file runs as a script, the interpreter sets the module's __name__ to the string "__main__". When the same file is imported, __name__ is the module's name ("greet"). The idiom that keeps a file usable both ways:
def total(nums):
return sum(nums)
def main():
nums = list(map(int, input().split()))
print(total(nums))
if __name__ == "__main__":
main()
Run as a script, main() executes. Imported by a test file that wants total, it does not — no input is read, nothing is printed. Two habits come with the idiom: put the program's work in a main() function rather than at top level, so that the names it creates are local and the file has one obvious entry point; and keep the guard at the bottom, after every definition it needs.
Exit codes
A process ends with an integer status: 0 means success, anything else means failure, and shells, CI systems and the study judge read it. A Python program that reaches the end of the file exits 0. sys.exit(2) exits with 2; sys.exit("message") prints the message to stderr and exits 1; an uncaught exception prints a traceback to stderr and exits 1.
import sys
if len(sys.argv) < 2:
print("usage: tool.py <file>", file=sys.stderr)
sys.exit(2)
Errors go to standard error, not standard output, so that a program whose output is piped somewhere does not corrupt it with messages.
How the judge runs your program
Every exercise in this track is a whole program. The judge writes your source to Main.py, runs it once per test case with that case's input on standard input, captures standard output, and compares it with the expected output after ignoring trailing spaces on each line and trailing blank lines. Three consequences:
- Standard error is ignored for the comparison — but a non-zero exit code is a runtime error verdict, so an uncaught exception fails the case even if the right output was printed first, and
sys.exit(1)fails it too. - Read with
input()orsys.stdin, never with a prompt.input("Enter n: ")writesEnter n:to standard output, which becomes part of your answer and fails the comparison. Bareinput()is the rule. - There is a time limit of about a second per case. Every exercise here is designed to run in milliseconds; a program that takes seconds has the wrong algorithm.
The interpreter is CPython 3.11 on Linux. Features newer than 3.11 do not exist there, and the lesson text marks them.
Useful flags
| Flag | Effect |
|---|---|
-i | Enter the REPL after the script finishes (or fails) |
-c "code" | Run the string as a program |
-m mod | Run a module as a script |
-X dev | Development mode: extra warnings, ResourceWarning for unclosed files |
-O | Strip assert statements (Module 10 explains why that matters) |
-u | Unbuffered stdout, so prints appear immediately when piped |
-W error | Turn warnings into exceptions |
--version | Print the version and exit |
Pitfalls
- Expecting a script to echo expression values like the REPL does. Only
printprints in a script. - Calling a function above its
def. Definitions are executed in order; the call must come after. - Putting work at module top level in a file you also import. The main guard exists for this.
- Using
input("prompt")in a judged program. The prompt is output. pythonpointing at a different interpreter thanpip.python -m pipalways matches.
Key takeaways
- The REPL echoes expression values; scripts print only what you
print. python -m moduleruns a module as a script by its import name;-cruns a string;-ikeeps the REPL open afterwards.__name__ == "__main__"is true only when the file runs as the script; keep the work inmain()under that guard.- Exit
0is success; an uncaught exception orsys.exit(non-zero)is failure — and a runtime error on the judge. - Judged programs read from stdin with bare
input()/sys.stdin, print to stdout, and finish within a second.
Common questions
How do I run a Python script from the command line?
Run python script.py, or python3 script.py on systems where python is still Python 2. The interpreter compiles the whole file, then executes it top to bottom; unlike the REPL, a script prints nothing unless you call print. python -i script.py runs it and then opens the REPL with its names defined.
What does python -m do?
python -m module runs a module as a script, found by its import name on the import path rather than by a file path. Standard-library tools are run this way — python -m venv .venv, python -m http.server 8000, python -m json.tool — and python -m pip always installs into that same interpreter.
What is the Python REPL?
The REPL (read–eval–print loop) is the interactive prompt you get by running python with no arguments. It evaluates each line, echoes an expression's value using repr, keeps the last value in _, and offers help() and dir() for quick lookups. Leave it with exit() or Ctrl-D.
What exit code does a Python script return?
A script that reaches the end of the file exits with status 0, which means success. sys.exit(2) exits with 2, sys.exit("message") prints the message to standard error and exits with 1, and an uncaught exception prints a traceback to standard error and exits with 1.
Why does calling a function before its def raise NameError?
A def statement binds the function's name only when execution reaches it, so a call placed above the def runs while the name does not exist yet. Definitions execute in order; put the calls after them, typically inside a main() called at the bottom of the file.
Exercises
Classify the invocation
Read n command lines, each starting with python or python3, and say how the interpreter would run: with no arguments it opens the REPL; -c runs a command; -m <name> runs a module; -i <file> runs a script and then opens the REPL; a bare file name runs a script. Anything after the module or file name (extra arguments) is ignored.
Input: n, then n command lines. Output: one line per command: REPL, command, module <name>, script <file> then REPL or script <file>.
4
python app.py
python -m json.tool
python
python -c "print(1)"
prints
script app.py
module json.tool
REPL
commandA script with a main guard
Write a program in the shape every serious script has: a function total(nums) that returns the sum of a list of integers, a main() that does all the reading and printing, and the if __name__ == "__main__": guard as the only top-level statement that runs code. main() reads lines until the end of input; each line holds integers separated by spaces. Print the sum of each line, then a final line total: <sum of everything>.
Input: zero or more lines of integers. Output: one sum per input line, then total: <n>.
1 2 3
10 20
prints
6
30
total: 36In this module: Python and the interpreter
- What Python is, and why it looks the way it does
- Running Python — the REPL, scripts, modules and the judge (this lesson)
- Anatomy of a Python program
- Console input and output — the patterns every exercise uses
- Errors and tracebacks — reading what the interpreter tells you
- Checkpoint — Python and the interpreter
← What Python is, and why it looks the way it does · Anatomy of a Python program →