🐍Your First Python Project with Claude
Build a complete Python script that talks to Claude — from setup to running
Your First Python Project with Claude
This is it -- the moment you go from reading about Claude to actually building something with it. By the end of this lesson, you will have a fully working Python script that sends messages to Claude and gets intelligent responses back.
We will go step by step. No shortcuts.
Step 1: Install Python
First, make sure Python is installed on your computer.
Check if Python is Already Installed
Open your terminal (macOS/Linux) or Command Prompt (Windows) and type:
python3 --versionIf you see something like Python 3.10.12 or higher, you are good. If not, install it:
- macOS:
brew install python3(or download from python.org) - Windows: Download from python.org and check "Add Python to PATH" during installation
- Linux:
sudo apt install python3 python3-pip
Also verify pip (Python's package manager):
pip3 --versionStep 2: Create a Project Folder
Organization matters. Create a dedicated folder for this project:
mkdir claude-first-project
cd claude-first-projectStep 3: Set Up a Virtual Environment
A virtual environment keeps your project's dependencies isolated from other projects. This is a best practice.
python3 -m venv venvActivate it:
- macOS/Linux:
source venv/bin/activate- Windows:
venv\Scripts\activateYou will see (venv) appear before your terminal prompt. This means the virtual environment is active.
Why a virtual environment? Without it, packages you install could conflict with other projects. Each virtual environment is its own little sandbox.
Step 4: Install the Anthropic SDK
Now install the official Anthropic Python library:
pip install anthropicVerify the installation:
pip show anthropicYou should see the package name, version, and other details.
Step 5: Set Your API Key
You need the API key you created in the Console lesson. Set it as an environment variable:
macOS/Linux:
undefinedWindows (PowerShell):
$env:ANTHROPIC_API_KEY = "sk-ant-api03-your-key-here"Important: Replace
sk-ant-api03-your-key-herewith your actual key. The Anthropic SDK automatically reads this environment variable, so you do not need to pass it in your code.
Step 6: Your First Script -- Hello Claude
Create a file called hello_claude.py:
# Create the client (automatically reads ANTHROPIC_API_KEY)
client = anthropic.Anthropic()
# Send a message to Claude
message = client.messages.create(
model="claude-sonnet-4-6-20250514",
max_tokens=1024,
messages=[
{"role": "user", "content": "Hello Claude! What can you help me with?"}
]
)
# Print the response
print(message.content[0].text)Run it:
python3 hello_claude.pyIf everything is set up correctly, Claude will respond with a friendly message about how it can help you. Congratulations -- you just made your first API call!
Understanding the Code
Let us break down every line:
| Line | What It Does |
|---|---|
import anthropic | Imports the Anthropic SDK |
client = anthropic.Anthropic() | Creates a client that handles API communication |
client.messages.create(...) | Sends a message to Claude and waits for a response |
model="claude-sonnet-4-6-20250514" | Specifies which Claude model to use |
max_tokens=1024 | Limits the response length to 1024 tokens |
messages=[...] | The conversation history (just one message here) |
message.content[0].text | Extracts the text from Claude's response |
Step 7: Adding a System Prompt
A system prompt gives Claude a role or personality. Create claude_tutor.py:
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-4-6-20250514",
max_tokens=1024,
system="You are a friendly Python tutor. Explain everything as if the user is a complete beginner. Use simple analogies and include code examples in every response.",
messages=[
{"role": "user", "content": "What is a variable in Python?"}
]
)
print(message.content[0].text)Run it:
python3 claude_tutor.pyNotice how the response is now tailored to a beginner audience, with analogies and code examples. That is the power of the system prompt.
Step 8: Multi-Turn Conversation
Real conversations have multiple turns. Claude uses the full message history to understand context. Create multi_turn.py:
client = anthropic.Anthropic()
# Build a multi-turn conversation
messages = [
{"role": "user", "content": "My name is Alex and I am learning Python."},
{"role": "assistant", "content": "Nice to meet you, Alex! Python is a great choice for learning programming. What would you like to start with?"},
{"role": "user", "content": "What was my name again?"}
]
response = client.messages.create(
model="claude-sonnet-4-6-20250514",
max_tokens=1024,
messages=messages
)
print(response.content[0].text)Run it:
python3 multi_turn.pyClaude will correctly say "Your name is Alex" because it has the full conversation history. Each message in the messages list alternates between "user" and "assistant" roles.
Key Rule: Message Alternation
Messages must alternate between user and assistant:
user -> assistant -> user -> assistant -> user
You cannot have two user messages in a row or two assistant messages in a row.
Step 9: Interactive Chat Loop
Now let us build a real interactive chatbot that runs in your terminal. Create chat.py:
client = anthropic.Anthropic()
SYSTEM_PROMPT = """You are a helpful AI assistant. You are friendly,
concise, and helpful. If you do not know something, say so honestly."""
def chat_with_claude():
"""Run an interactive chat session with Claude."""
conversation_history = []
print("=" * 50)
print(" Chat with Claude")
print(" Type 'quit' to exit")
print(" Type 'clear' to start a new conversation")
print("=" * 50)
print()
while True:
# Get user input
user_input = input("You: ").strip()
# Handle special commands
if user_input.lower() == "quit":
print("\nGoodbye!")
break
if user_input.lower() == "clear":
conversation_history = []
print("\n--- Conversation cleared ---\n")
continue
if not user_input:
continue
# Add user message to history
conversation_history.append({
"role": "user",
"content": user_input
})
try:
# Send to Claude
response = client.messages.create(
model="claude-sonnet-4-6-20250514",
max_tokens=2048,
system=SYSTEM_PROMPT,
messages=conversation_history
)
# Extract the response text
assistant_message = response.content[0].text
# Add assistant response to history
conversation_history.append({
"role": "assistant",
"content": assistant_message
})
# Print response with usage info
print(f"\nClaude: {assistant_message}")
print(f" [tokens: {response.usage.input_tokens} in / {response.usage.output_tokens} out]\n")
except anthropic.APIError as e:
print(f"\nAPI Error: {e}\n")
if __name__ == "__main__":
chat_with_claude()Run it:
python3 chat.pyYou now have a fully interactive chatbot in your terminal. Ask anything, have multi-turn conversations, and watch the token usage after each response.
Step 10: Save and Load Conversation History
A great chatbot should be able to save conversations and continue them later. Create chat_with_history.py:
from datetime import datetime
client = anthropic.Anthropic()
SYSTEM_PROMPT = """You are a helpful AI assistant. You are friendly,
concise, and helpful. If you do not know something, say so honestly."""
HISTORY_FILE = "chat_history.json"
def save_history(conversation_history):
"""Save conversation history to a JSON file."""
data = {
"saved_at": datetime.now().isoformat(),
"messages": conversation_history
}
with open(HISTORY_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
print(f" [History saved to {HISTORY_FILE}]")
def load_history():
"""Load conversation history from a JSON file."""
if not os.path.exists(HISTORY_FILE):
return []
try:
with open(HISTORY_FILE, "r", encoding="utf-8") as f:
data = json.load(f)
messages = data.get("messages", [])
saved_at = data.get("saved_at", "unknown")
print(f" [Loaded {len(messages)} messages from {saved_at}]")
return messages
except (json.JSONDecodeError, KeyError):
print(" [Warning: Could not load history, starting fresh]")
return []
def chat_with_claude():
"""Run an interactive chat session with Claude, with save/load support."""
conversation_history = load_history()
print("=" * 50)
print(" Chat with Claude (with history)")
print(" Commands:")
print(" quit - Exit the chat")
print(" clear - Clear conversation history")
print(" save - Save conversation to file")
print(" load - Reload conversation from file")
print(" count - Show message count")
print("=" * 50)
print()
while True:
user_input = input("You: ").strip()
# Handle commands
if user_input.lower() == "quit":
save_history(conversation_history)
print("\nGoodbye! History saved.")
break
if user_input.lower() == "clear":
conversation_history = []
print("\n--- Conversation cleared ---\n")
continue
if user_input.lower() == "save":
save_history(conversation_history)
continue
if user_input.lower() == "load":
conversation_history = load_history()
continue
if user_input.lower() == "count":
print(f" [{len(conversation_history)} messages in history]\n")
continue
if not user_input:
continue
# Add user message
conversation_history.append({
"role": "user",
"content": user_input
})
try:
response = client.messages.create(
model="claude-sonnet-4-6-20250514",
max_tokens=2048,
system=SYSTEM_PROMPT,
messages=conversation_history
)
assistant_message = response.content[0].text
conversation_history.append({
"role": "assistant",
"content": assistant_message
})
print(f"\nClaude: {assistant_message}")
print(f" [tokens: {response.usage.input_tokens} in / {response.usage.output_tokens} out]\n")
except anthropic.APIError as e:
print(f"\nAPI Error: {e}")
# Remove the failed user message
conversation_history.pop()
print(" [Message removed from history due to error]\n")
if __name__ == "__main__":
chat_with_claude()Run it:
python3 chat_with_history.pyNow you can:
- Chat with Claude interactively
- Type
saveto save the conversation tochat_history.json - Close the program and come back later
- The conversation loads automatically on startup
- Type
clearto start fresh
What the JSON History Looks Like
{
"saved_at": "2025-01-15T14:30:00.000000",
"messages": [
{
"role": "user",
"content": "Hello! My name is Alex."
},
{
"role": "assistant",
"content": "Hi Alex! Nice to meet you. How can I help you today?"
},
{
"role": "user",
"content": "Can you explain what a for loop is?"
},
{
"role": "assistant",
"content": "A for loop is a way to repeat a block of code..."
}
]
}Step 11: Error Handling
Production code needs proper error handling. Here are the common errors and how to handle them:
client = anthropic.Anthropic()
try:
response = client.messages.create(
model="claude-sonnet-4-6-20250514",
max_tokens=1024,
messages=[
{"role": "user", "content": "Hello!"}
]
)
print(response.content[0].text)
except anthropic.AuthenticationError:
print("ERROR: Invalid API key. Check your ANTHROPIC_API_KEY.")
except anthropic.RateLimitError:
print("ERROR: Rate limited. Wait a moment and try again.")
except anthropic.BadRequestError as e:
print(f"ERROR: Bad request - {e}")
except anthropic.APIConnectionError:
print("ERROR: Cannot connect to Anthropic API. Check your internet.")
except anthropic.APIStatusError as e:
print(f"ERROR: API returned status {e.status_code}: {e.message}")| Error | Cause | Fix |
|---|---|---|
AuthenticationError | Wrong or missing API key | Check ANTHROPIC_API_KEY |
RateLimitError | Too many requests too fast | Add a delay between requests |
BadRequestError | Invalid parameters | Check model name, message format |
APIConnectionError | No internet or API is down | Check connection, retry later |
APIStatusError | General API error | Check status code for details |
Full Working Project Structure
After completing all steps, your project folder looks like this:
claude-first-project/
venv/ # Virtual environment (do not edit)
hello_claude.py # Step 6: Basic API call
claude_tutor.py # Step 7: System prompt example
multi_turn.py # Step 8: Multi-turn conversation
chat.py # Step 9: Interactive chat loop
chat_with_history.py # Step 10: Chat with save/load
chat_history.json # Auto-generated conversation log
What You Learned
In this lesson you went from zero to a fully working Python project:
| Step | What You Did |
|---|---|
| 1 | Installed Python and verified the installation |
| 2 | Created a dedicated project folder |
| 3 | Set up a virtual environment for isolation |
| 4 | Installed the Anthropic Python SDK |
| 5 | Configured your API key as an environment variable |
| 6 | Made your first API call to Claude |
| 7 | Used a system prompt to control Claude's behavior |
| 8 | Built a multi-turn conversation |
| 9 | Created an interactive chat loop in the terminal |
| 10 | Added save and load for conversation history |
| 11 | Implemented proper error handling |
Common Troubleshooting
| Problem | Solution |
|---|---|
ModuleNotFoundError: anthropic | Run pip install anthropic (make sure venv is active) |
AuthenticationError | Check that ANTHROPIC_API_KEY is set correctly |
python3: command not found | Install Python from python.org |
| Response is cut off | Increase max_tokens value |
venv not activating | Make sure you are using the right command for your OS |
Next up: We will dive into the Claude Code CLI -- a powerful terminal tool that lets Claude help you code directly in your projects.