Run and Test Your First Script
This page is for beginners who already installed uv on a Mac (Environment setup).
Input and Output
Section titled “Input and Output”Every Python script you run is a small program that takes input (the keyboard in this walkthrough; files and APIs later), runs your code, and produces output (usually text in the terminal).
flowchart LR input["Input"] app["Python app main.py"] output["Output"] input --> app --> output
You will:
- Create a project folder.
- Write a few lines of Python and run them.
- Optionally check that Python is using your project’s isolated environment (a virtual environment, or venv — a private copy of Python and packages for this folder only).
- Read name and age from the keyboard with
input(). - Check that name and age look valid before you use them.
- Try a quick
assertself-check, then a simple automated test with pytest (a popular test tool).
Run each command in Terminal right after the step that shows it. You should see output similar to what each step describes.
What you will have at the end: a folder called hello_uv/ containing main.py, test_main.py, and a hidden-style .venv/ folder that holds your project’s Python.
You do not need to write any def functions in the app script. Later steps use input() and simple if checks; pytest test files use def only because that is how pytest finds tests.
Step 1 — Create the Project Folder
Section titled “Step 1 — Create the Project Folder”Goal: Make a new folder and tell uv to set up Python for it.
Run these commands one at a time (or copy the block — && means “run the next command only if the previous one succeeded”):
mkdir hello_uvcd hello_uvuv init --python 3.12uv venvWhat each command does:
| Command | What it does |
|---|---|
mkdir hello_uv | Creates a new folder named hello_uv. |
cd hello_uv | Moves you inside that folder. |
uv init --python 3.12 | Creates main.py and pyproject.toml (a small config file for the project). |
uv venv | Creates .venv/ — your project’s private Python environment. |
You should now see something like:
hello_uv/ pyproject.toml .venv/ main.pyStep 2 — Write and Run main.py
Section titled “Step 2 — Write and Run main.py”Goal: Put three lines of Python in main.py and run the file.
Open main.py in any text editor. Replace everything in the file with:
name = "world"message = "Hello, " + name + "!"print(message)Line by line:
name = "world"— store the text"world"in a variable calledname.message = "Hello, " + name + "!"— build a new string and store it inmessage.print(message)— showmessagein the terminal.
Run it from inside the hello_uv folder:
uv run python main.pyYou should see:
Hello, world!uv run runs Python using your project’s .venv — you do not need to run source .venv/bin/activate first.
If you get No such file or directory, make sure you ran cd hello_uv and that main.py is saved in that folder.
Step 3 — Optional: Check Which Python You Are Using
Section titled “Step 3 — Optional: Check Which Python You Are Using”Goal: Confirm Python is coming from .venv, not macOS system Python.
This step is optional. Skip it if the script already printed Hello, world! and you want to keep moving.
uv run python -c "import sys; print(sys.executable)"You should see a path that includes hello_uv and .venv. That means your project environment is in use.
Another way some tutorials use — turn the environment on manually, then turn it off:
source .venv/bin/activatewhich pythonpython main.pydeactivateAfter activate, your shell prompt may show (.venv). The which python path should end with hello_uv/.venv/bin/python.
Step 4 — Read name and age From Input
Section titled “Step 4 — Read name and age From Input”Goal: Add an age variable and read both values from the keyboard when you run the script.
Update main.py to:
name = input("Your name: ")age = input("Your age: ")message = "Hello, " + name + "! You are " + age + " years old."print(message)| Line | What it does |
|---|---|
input("...") | Pauses and reads one line from the keyboard. Always returns a string, even for age. |
message = ... | Builds one string from name and age, then print shows it in the terminal. |
Run it:
uv run python main.pyType a name and age when prompted. Example session:
Your name: AdaYour age: 25Hello, Ada! You are 25 years old.Step 5 — Basic Validation on name and age
Section titled “Step 5 — Basic Validation on name and age”Goal: Print an error instead of the greeting when input does not look right.
Rules for this walkthrough:
- Name: letters only — use
isalpha()on the string (no spaces or digits in this simple check). - Age: digits only — use
isdigit()before you use the value.
Both are string methods — functions you call on a str value with dot notation (name.isalpha()). The official Python docs list all of them under built-in string methods (isalnum(), isnumeric(), isspace(), and others).
Wrap the greeting in if / elif / else so you only build message when both checks pass:
name = input("Your name: ")age = input("Your age: ")
if not name.isalpha(): print("Error: name must contain letters only.")elif not age.isdigit(): print("Error: age must be a number.")else: message = "Hello, " + name + "! You are " + age + " years old." print(message)Plain English:
if not ...— if the name fails, print one error and skip the greeting.elif— check age only when the name was OK.else— both checks passed; safe to buildmessageandprint.
Try it:
- Valid input —
Adaand25— you see the greeting. - Invalid name —
Ada3— onlyError: name must contain letters only. - Invalid age —
twenty— onlyError: age must be a number.
input() always returns a string
Section titled “input() always returns a string”input() has no “int mode” — every line you read is a str, even when it looks like a number ("25", not 25). That is why Step 5 checks age.isdigit() on the string first.
When you need to do math, convert after the check with int():
age = input("Your age: ")if age.isdigit(): age_num = int(age) # now it's an int print(age_num + 1) # 26In the greeting script above, keeping age as a string in message is fine ("You are 25 years old."). Use int(age) only when you need numeric comparisons or arithmetic.
Check input as soon as it enters your program — the same idea as validating an API request before you use it deeper in the stack, kept tiny here.
Step 6 — A Quick Self-Check With assert
Section titled “Step 6 — A Quick Self-Check With assert”Goal: Ask Python to verify your message was built correctly before printing it.
An assert line means: “stop with an error if this is not true.” Useful for a tiny script; later you will use a test file instead.
Add one line in the else branch, after you build message:
name = input("Your name: ")age = input("Your age: ")
if not name.isalpha(): print("Error: name must contain letters only.")elif not age.isdigit(): print("Error: age must be a number.")else: message = "Hello, " + name + "! You are " + age + " years old." assert message == "Hello, " + name + "! You are " + age + " years old." print(message)Run it again (valid input at the prompt):
uv run python main.pyYou should still see your greeting. To see AssertionError, change the right-hand side of the assert to a different string — that is the check catching a mismatch.
Step 7 — Add pytest and a Test File
Section titled “Step 7 — Add pytest and a Test File”Goal: Run checks in a separate file so your main script stays simple.
pytest runs test functions in files whose names start with test_. Online tutorials often say pip install pytest; with uv you run:
uv add --dev pytestThe --dev flag means “only needed for development/testing,” not for running the app in production.
Wrap interactive code so pytest does not wait for input
Section titled “Wrap interactive code so pytest does not wait for input”When pytest loads main.py, Python runs the whole file. If input() sits at the top level, tests would pause for keyboard input.
Add default values at the top and move the interactive part under if __name__ == "__main__":. Remove the assert from Step 6 — the test file will cover those checks.
name = "world"age = "30"message = "Hello, " + name + "! You are " + age + " years old."
if __name__ == "__main__": name = input("Your name: ") age = input("Your age: ")
if not name.isalpha(): print("Error: name must contain letters only.") elif not age.isdigit(): print("Error: age must be a number.") else: message = "Hello, " + name + "! You are " + age + " years old." print(message)Plain English: if __name__ == "__main__": means “only run the indented lines when I execute this file directly (uv run python main.py), not when something else imports this file.” The defaults at the top are what pytest reads.
Create test_main.py
Section titled “Create test_main.py”In the same folder as main.py, create a new file test_main.py:
from main import age, message, name
def test_message(): assert message == "Hello, world! You are 30 years old."
def test_name(): assert name == "world"
def test_age(): assert age == "30"
def test_validation_examples(): assert "Ada".isalpha() assert not "Ada3".isalpha() assert "25".isdigit() assert not "twenty".isdigit()What this means:
from main import age, message, name— read the default variables frommain.py(pytest loadsmain.pywithout running theinput()block).def test_message():,def test_name():, and so on — pytest looks for functions whose names start withtest_. You are not writing app logic here; this is pytest’s required shape. You will learndefproperly in Language basics.test_validation_examples— rehearses the same.isalpha()and.isdigit()checks from Step 5 using fixed strings (no keyboard input).
Run tests:
uv run pytestuv run pytest -vExpected:
4 passedStep 8 — What to Do Next
Section titled “Step 8 — What to Do Next”- Language basics — variables,
if/elif/else, loops, and laterdeffunctions. - Process log files — a longer stdlib script; save it as another
.pyfile in the same project and run withuv run python process_logs.py. - Install another package —
uv add package-name(see Translating pip commands to uv if a tutorial sayspip install).
Key Takeaways
Section titled “Key Takeaways”mkdir+uv init+uv venv— create a project with its own Python in.venv/.uv run python main.py— run your script using that environment.input()— read a line from the user as a string..isalpha()/.isdigit()— quick shape checks on strings.if/elif/else— run the greeting only when validation passes.assert— a one-line “this must be true” check; fine for learning, pytest scales better later.if __name__ == "__main__":— run code only when the file is executed directly, not when imported by tests.uv add --dev pytestthenuv run pytest— findstest_*.pyfiles and runs functions namedtest_....
Words You Might See
Section titled “Words You Might See”| Term | Plain meaning |
|---|---|
venv (.venv/) | A private Python + packages folder for this project only. |
| uv run | Run a command inside the project venv without activating it manually. |
| input | Built-in that reads one line from the keyboard and returns a string. |
| validation | Checking that data looks right before you use it. |
| elif | “Else if” — try the next condition only when the previous if was false. |
| pytest | A tool that finds and runs test files. |
| import | Load code or variables from another file in the same project. |