Basic_Python / app.py
eaglelandsonce's picture
Update app.py
0454eec verified
Raw
History Blame Contribute Delete
13.6 kB
import gradio as gr
import io
import contextlib
import traceback
# ---------- Python runner ----------
def run_python(code: str) -> str:
"""
Execute user-provided Python code and capture stdout / errors.
NOTE: This is for teaching demos; do NOT use this pattern in
a multi-user production environment without sandboxing.
"""
stdout_buffer = io.StringIO()
try:
# Provide a very simple, mostly empty environment
local_env = {}
global_env = {"__builtins__": __builtins__}
with contextlib.redirect_stdout(stdout_buffer):
exec(code, global_env, local_env)
output = stdout_buffer.getvalue()
if not output.strip():
output = "[No output produced]"
return output
except Exception:
error_text = stdout_buffer.getvalue()
error_text += "\n" + traceback.format_exc()
return error_text
# ---------- Course content ----------
lessons = [
{
"title": "Lesson 1: Setup & Simple Apps",
"description": """
### Lesson 1: Setting Up Python and Developing a Simple Application
**Topics**
- Topic A: Set Up the Development Environment
- Topic B: Write Python Statements
- Topic C: Create a Python Application
- Topic D: Prevent Errors
**You’ll practice:**
- Using `print()` and variables
- Reading user input with `input()`
- Building a tiny interactive console app
**Mini-project idea:**
Create a **“Profile Card”** script that asks for your name, age, and hobby, then prints a nicely formatted profile.
""",
"starter_code": '''# Lesson 1: Simple Hello & Input
print("👋 Welcome to Lesson 1: Setup & Simple Apps")
name = input("What is your name? ")
age = input("How old are you? ")
print(f"Hello, {name}! You are {age} years old.")
# Try:
# 1. Ask for a favorite color and food and add them to the message.
# 2. Create a small "profile card" printed with multiple lines, e.g.:
# Name: ...
# Age: ...
# Favorite color: ...
'''
},
{
"title": "Lesson 2: Simple Data Types",
"description": """
### Lesson 2: Processing Simple Data Types
**Topics**
- Topic A: Process Strings and Integers
- Topic B: Process Decimals, Floats, and Mixed Number Types
**You’ll practice:**
- Combining strings
- Doing arithmetic with integers and floats
- Using `round()` and basic numeric conversions
**Mini-project idea:**
Create a **BMI & Health Stats** script that asks for height, weight, and age, calculates BMI, and prints a short health summary.
""",
"starter_code": '''# Lesson 2: Strings, Integers, Floats
print("✨ Lesson 2: Simple Data Types")
first_name = "Alice"
last_name = "Smith"
age = 30
height_m = 1.70
weight_kg = 65.0
full_name = first_name + " " + last_name
bmi = weight_kg / (height_m ** 2)
print("Full name:", full_name)
print("Age next year:", age + 1)
print("BMI (unrounded):", bmi)
print("BMI (rounded to 2 decimals):", round(bmi, 2))
# Try:
# 1. Ask the user for their name and birth year; compute their age.
# 2. Convert a temperature from Fahrenheit to Celsius:
# celsius = (f - 32) * 5/9
# 3. Ask for two prices and print the subtotal, tax, and total.
'''
},
{
"title": "Lesson 3: Data Structures",
"description": """
### Lesson 3: Processing Data Structures
**Topics**
- Topic A: Process Ordered Data Structures (lists, tuples)
- Topic B: Process Unordered Data Structures (sets, dictionaries)
**You’ll practice:**
- Storing groups of values in lists and tuples
- Using sets to deduplicate data
- Using dictionaries to store labeled data
**Mini-project idea:**
Build a tiny **“Student Gradebook”** using a dictionary of names and scores. Compute averages and print a report.
""",
"starter_code": '''# Lesson 3: Lists, Tuples, Sets, Dictionaries
print("📚 Lesson 3: Data Structures")
# Ordered: lists and tuples
fruits = ["apple", "banana", "cherry"]
scores = (88, 92, 79)
print("Fruits:", fruits)
print("First fruit:", fruits[0])
print("Scores:", scores)
print("Average score:", sum(scores) / len(scores))
# Unordered: sets and dictionaries
numbers_with_duplicates = [1, 2, 2, 3, 3, 3]
unique_numbers = set(numbers_with_duplicates)
print("Original numbers:", numbers_with_duplicates)
print("Unique numbers:", unique_numbers)
student = {
"name": "Alice",
"age": 20,
"grade": "A"
}
print("Student name:", student["name"])
print("\nAll student key/value pairs:")
for key, value in student.items():
print(f"{key}: {value}")
# Try:
# 1. Add a new key "major" to the student dictionary, then print it.
# 2. Create a list of 5 movies and print the first and last.
# 3. Create a "gradebook" dict: student_name -> list of scores,
# then print each student's average.
'''
},
{
"title": "Lesson 4: Conditionals & Loops",
"description": """
### Lesson 4: Writing Conditional Statements and Loops
**Topics**
- Topic A: Write a Conditional Statement (`if`, `elif`, `else`)
- Topic B: Write a Loop (`for`, `while`)
**You’ll practice:**
- Making decisions in code
- Repeating actions until some condition is met
- Combining `if` with loops for basic logic
**Mini-project idea:**
Create a **“Number Guessing Game”** that picks a random number and gives the user several attempts with hints (too high / too low).
""",
"starter_code": '''# Lesson 4: Conditionals & Loops
print("🔁 Lesson 4: Conditionals and Loops")
# Conditional example
score = int(input("Enter a score between 0 and 100: "))
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
elif score >= 60:
grade = "D"
else:
grade = "F"
print(f"Your grade is: {grade}")
# Loop example: print even numbers 2-20
print("\nEven numbers from 2 to 20:")
for n in range(2, 21, 2):
print(n, end=" ")
print() # newline
# Try:
# 1. Use a while loop to ask for a password until it is 'secret'.
# 2. Write an if/elif/else to classify a number as positive, negative, or zero.
# 3. (Challenge) Make a number guessing game (1-20) that tells the user if
# their guess is too high or too low.
'''
},
{
"title": "Lesson 5: Functions, Classes, Modules",
"description": """
### Lesson 5: Structuring Code for Reuse
**Topics**
- Topic A: Define and Call a Function
- Topic B: Define and Instantiate a Class
- Topic C: Import and Use a Module
**You’ll practice:**
- Creating functions with parameters and return values
- Creating simple classes with attributes and methods
- Using built-in modules like `math`, `random`
**Mini-project idea:**
Create a **“Banking Simulator”** with a `BankAccount` class that supports deposit, withdraw, and showing balance.
""",
"starter_code": '''# Lesson 5: Functions, Classes, and Modules
print("🧩 Lesson 5: Reusable Code")
# --- Functions ---
def add(a, b):
"""Return the sum of a and b."""
return a + b
result = add(10, 5)
print("10 + 5 =", result)
# --- Classes ---
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def description(self):
return f"{self.year} {self.make} {self.model}"
my_car = Car("Toyota", "Corolla", 2022)
print("My car:", my_car.description())
# --- Modules ---
import math
import random
print("Square root of 16:", math.sqrt(16))
print("Random integer from 1 to 6:", random.randint(1, 6))
# Try:
# 1. Write a function is_even(n) that returns True if n is even.
# 2. Create a BankAccount class with deposit and withdraw methods,
# and test it with a few transactions.
# 3. Use random.randint to simulate rolling two dice and print their sum.
'''
},
{
"title": "Lesson 6: Files & Directories",
"description": """
### Lesson 6: Writing Code to Process Files and Directories
**Topics**
- Topic A: Write to a Text File
- Topic B: Read from a Text File
- Topic C: Get the Contents of a Directory
- Topic D: Manage Files and Directories
⚠️ In a hosted environment, file access is temporary and sandboxed,
but the patterns you learn here transfer directly to your local machine.
**You’ll practice:**
- Creating directories and files
- Reading and writing text data
- Listing directory contents
**Mini-project idea:**
Create a simple **“Log Writer”** that appends timestamped messages to a log file, then reads and prints the last N lines.
""",
"starter_code": '''# Lesson 6: Files & Directories
print("📂 Lesson 6: Files and Directories")
from pathlib import Path
# Create a folder
folder = Path("demo_folder")
folder.mkdir(exist_ok=True)
# Write to a file
file_path = folder / "example.txt"
file_path.write_text("Hello from Lesson 6!\\nThis is a test file.")
print("Wrote file:", file_path)
# Read from a file
content = file_path.read_text()
print("\\nFile contents:")
print(content)
# List directory contents
print("\\nContents of demo_folder:")
for item in folder.iterdir():
print(" -", item.name)
# Try:
# 1. Add another file with different text.
# 2. Read both files and print their contents.
# 3. Add a timestamp to each line you write into a 'log.txt' file.
'''
},
{
"title": "Lesson 7: Exceptions",
"description": """
### Lesson 7: Dealing with Exceptions
**Topics**
- Topic A: Handle Exceptions
- Topic B: Raise Exceptions
**You’ll practice:**
- Wrapping risky code in `try/except`
- Catching specific errors like `ValueError` and `ZeroDivisionError`
- Raising your own exceptions when inputs are invalid
**Mini-project idea:**
Create a **“Safe Calculator”** that:
- Accepts user input for operations
- Handles invalid inputs gracefully
- Prevents divide-by-zero errors
""",
"starter_code": '''# Lesson 7: Exceptions
print("⚠️ Lesson 7: Exceptions")
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
print("Error: cannot divide by zero!")
return None
x = float(input("Enter numerator: "))
y = float(input("Enter denominator: "))
result = safe_divide(x, y)
print("Result:", result)
# Raising your own exception
def set_age(age):
if age < 0 or age > 120:
raise ValueError("Age must be between 0 and 120.")
return age
try:
age_value = int(input("Enter an age (0-120): "))
print("Valid age:", set_age(age_value))
except ValueError as e:
print("Invalid age:", e)
# Try:
# 1. Wrap more user input in try/except to catch ValueError.
# 2. Write a function that raises ValueError if a discount is
# not between 0 and 100.
# 3. Build a small "safe calculator" that handles bad input gracefully.
'''
},
]
appendix_markdown = """
## 📎 References & Appendices
This tab consolidates extra reference material for the course.
---
### Appendix A: Major Differences Between Python 2 and 3
Modern development uses **Python 3**, but here are some historical differences:
- `print`
- Python 2: `print "Hello"`
- Python 3: `print("Hello")`
- Integer division
- Python 2: `5/2` → `2` (integer when both are ints)
- Python 3: `5/2` → `2.5`, use `5//2` for integer division.
- Text and bytes
- Python 2: `str` (bytes) vs `unicode`.
- Python 3: `str` is Unicode by default; `bytes` is a separate type.
- `input()`
- Python 2: `input()` evaluates, `raw_input()` returns string.
- Python 3: `input()` always returns a string.
- Standard library layout
- Some modules reorganized (e.g., `urllib` family).
If you’re starting now, you almost never need Python 2, but you might see old code in the wild.
---
### Appendix B: Mini Python Style Guide (PEP 8 Highlights)
Follow these conventions to keep your code clean and readable:
**Indentation**
- Use **4 spaces** per indentation level.
- Avoid mixing tabs and spaces.
**Naming**
- Variables / functions: `snake_case` (e.g., `total_price`, `calculate_bmi`).
- Classes: `CapWords` (e.g., `BankAccount`).
- Constants: `UPPER_CASE` (e.g., `PI = 3.14159`).
**Spacing**
- Around operators: `x = a + b`, not `x=a+b`.
- After commas: `func(a, b, c)`.
**Imports**
- At the **top** of the file.
- One import per line is preferred.
**Comments & Docstrings**
- Use `#` for short explanations above a line or block.
- Use triple-quoted strings for docstrings, for example:
`\"\"\"This is a multi-line docstring.\"\"\"`.
**Structure**
- Break large scripts into functions and classes.
- For larger programs, use:
```python
if __name__ == "__main__":
main()
with gr.Tabs():
# Main lesson tabs
for lesson in lessons:
with gr.Tab(lesson["title"]):
gr.Markdown(lesson["description"])
code = gr.Code(
value=lesson["starter_code"],
language="python",
label="✏️ Edit and run your Python code here",
interactive=True,
)
with gr.Row():
run_button = gr.Button("▶️ Run code", variant="primary")
clear_button = gr.Button("🧹 Clear output")
output = gr.Textbox(
label="📤 Output (stdout and errors)",
lines=14,
show_copy_button=True,
)
# Bind buttons
run_button.click(run_python, inputs=code, outputs=output)
clear_button.click(lambda: "", outputs=output)
# References / Appendices tab
with gr.Tab("References & Appendices"):
gr.Markdown(appendix_markdown)
gr.Markdown(
"""