Python with AI Tutorial · Chapter 43 of 48
To call an AI API from Python you install the provider’s SDK, read your API key from an environment variable, and send a prompt to a model such as OpenAI’s GPT-5 or Anthropic’s Claude Sonnet 5. The reply comes back as a Python object you can print, parse as JSON or write into a report. This chapter shows both providers side by side.
Install the SDKs
Both companies publish official packages on PyPI. Install them in your project virtual environment from chapter 25.
# in the terminal, not in Python
pip install openai anthropic
Output: Successfully installed openai-... anthropic-... httpx-... pydantic-...
Keep the API key out of your code
Create a key in the OpenAI or Anthropic console, then store it as an environment variable. On Windows run setx OPENAI_API_KEY "sk-..." and open a new terminal; on macOS or Linux add export OPENAI_API_KEY="sk-..." to your shell profile. Do the same for ANTHROPIC_API_KEY. The SDKs read these variables automatically, so the key never appears in a script that you might share or commit to Git.
import os
for name in ["OPENAI_API_KEY", "ANTHROPIC_API_KEY"]:
value = os.environ.get(name)
print(name, "found" if value else "MISSING - set it and reopen the terminal")
Output: OPENAI_API_KEY found ANTHROPIC_API_KEY found
Your first OpenAI request
The Responses API is the current entry point. Create a client, name a model, pass your text as input and read output_text. Because language models are not deterministic, the wording you get back will differ slightly from the sample output.
from openai import OpenAI
client = OpenAI() # reads OPENAI_API_KEY
response = client.responses.create(
model="gpt-5",
input="In one sentence, why should a small business track gross margin?",
)
print(response.output_text)
Output: Gross margin shows how much of each sale is left to cover overheads and profit, so tracking it reveals pricing and cost problems early.
The older client.chat.completions.create(model="gpt-5", messages=[{"role": "user", "content": "..."}]) form still works and appears in many tutorials; the answer is then in completion.choices[0].message.content.
Your first Anthropic request
The Anthropic SDK uses a messages list and requires max_tokens, the cap on the length of the reply. The text is in the first content block.
import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[
{"role": "user", "content": "In one sentence, why should a small business track gross margin?"}
],
)
print(message.content[0].text)
Output: Tracking gross margin tells you whether each sale actually contributes to running the business, before overheads eat the revenue.
Add a system prompt
A system prompt sets the role, tone and format for every reply. OpenAI calls it instructions; Anthropic calls it system. Both are ordinary strings.
from openai import OpenAI
import anthropic
role = "You are a finance analyst. Answer with at most three short bullet points."
question = "What causes cash flow problems in a profitable company?"
oa = OpenAI().responses.create(model="gpt-5", instructions=role, input=question)
print(oa.output_text)
an = anthropic.Anthropic().messages.create(
model="claude-sonnet-5", max_tokens=300, system=role,
messages=[{"role": "user", "content": question}],
)
print(an.content[0].text)
Output: - Customers pay late while suppliers demand payment now - Cash tied up in inventory or unbilled work - Growth funded from working capital without a credit line - Slow receivables collection - Stock that sits unsold - Loan repayments and tax bills timed against revenue
Get JSON you can process
Ask for a strict format and parse it. This classifies support tickets, a task that used to need hand-written keyword rules.
import json
import anthropic
tickets = [
"Invoice 4471 was charged twice",
"How do I export the report to Excel?",
"The dashboard still shows 2024 data",
]
prompt = (
"Classify each ticket as billing, how-to or bug. Reply with JSON only, "
"no code fences: a list of objects with keys ticket and category.\n"
+ "\n".join(tickets)
)
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-5", max_tokens=500,
messages=[{"role": "user", "content": prompt}],
)
rows = json.loads(message.content[0].text)
for row in rows:
print(f"{row['category']:8} {row['ticket']}")
Output: billing Invoice 4471 was charged twice how-to How do I export the report to Excel? bug The dashboard still shows 2024 data
Let the assistant turn the classifier into a reusable function with a fallback for malformed replies.
Refactor this Python code into a function classify_tickets(tickets: list[str]) -> list[dict] using the anthropic SDK with model claude-sonnet-5. If json.loads fails, retry once with a stricter instruction, then raise ValueError. Read the key from ANTHROPIC_API_KEY. Here is the code: [paste the JSON example above]
Handle errors and rate limits
Both SDKs raise typed exceptions and retry transient failures twice by default. Every account also has rate limits, measured in requests and tokens per minute, that rise as you spend more. Catch the specific errors so your script fails with a useful message.
import openai
from openai import OpenAI
client = OpenAI(max_retries=3)
try:
r = client.responses.create(model="gpt-5", input="Reply with the word OK.")
print(r.output_text)
except openai.AuthenticationError:
print("Check OPENAI_API_KEY")
except openai.RateLimitError:
print("Rate limit or quota reached - wait, then retry")
except openai.APIStatusError as e:
print("API error", e.status_code, e.message)
Output: OK
The Anthropic equivalents are anthropic.AuthenticationError, anthropic.RateLimitError and anthropic.APIStatusError.
Watch tokens and cost
You pay per token, roughly four characters of English, with separate prices for input and output. A 300-word question and a 300-word answer is about 800 tokens, which costs a fraction of a cent on mid-tier models; long documents and thousands of calls are where bills grow. Every response reports its usage, so log it.
import anthropic
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-5", max_tokens=200,
messages=[{"role": "user", "content": "Give me three KPI names for a retail store."}],
)
print("input tokens: ", message.usage.input_tokens)
print("output tokens:", message.usage.output_tokens)
# OpenAI: response.usage.input_tokens and response.usage.output_tokens
Output: input tokens: 19 output tokens: 41
Ask for a cost estimate before you run a big batch.
I will send 2,000 product descriptions of about 120 words each to an AI API and ask for a 30-word summary of each. Estimate total input and output tokens, then show the Python code that accumulates usage.input_tokens and usage.output_tokens across the loop and prints a running total.
Choose a model deliberately
Every provider sells a range: small, fast, cheap models for classification and extraction, and large models for reasoning and long documents. Start with the cheapest model that passes your tests, and keep the name in one place, ideally an environment variable, so you can switch without editing ten files. Model names change every few months; the provider consoles list what is current.
import os
from openai import OpenAI
MODEL = os.environ.get("AI_MODEL", "gpt-5-mini")
client = OpenAI()
r = client.responses.create(model=MODEL, input="Name one KPI for a bakery, no explanation.")
print(MODEL, "->", r.output_text)
Output: gpt-5-mini -> Daily sales per labour hour
Requests are stateless
Each call is independent: the model does not remember your previous request unless you send it again. That is why a single question works with one create call, while a conversation needs a list of messages that grows with every turn. The next chapter builds exactly that. For now, treat every call as a function: prompt in, text out, and keep any state in your own Python variables.
Common mistakes
- Hard-coding the key in the script, then pushing it to GitHub. Use environment variables from day one.
- Forgetting
max_tokenswith Anthropic, or setting it so low that answers are cut off mid-sentence. - Parsing the reply with
json.loadswithout asking for "JSON only, no code fences". - Looping over thousands of rows with no usage logging and no spending limit.
- Using an old model name copied from a 2023 tutorial; check the provider’s model list.
Exercise
Write a function translate(text, language) that uses either SDK to translate a product description and returns only the translated text. Call it for "Stainless steel water bottle, 750 ml" in German and French.
Show answer
from openai import OpenAI
client = OpenAI()
def translate(text: str, language: str) -> str:
r = client.responses.create(
model="gpt-5",
instructions=f"Translate the user text into {language}. Reply with the translation only.",
input=text,
)
return r.output_text.strip()
for lang in ["German", "French"]:
print(lang, "->", translate("Stainless steel water bottle, 750 ml", lang))
Output: German -> Edelstahl-Trinkflasche, 750 ml French -> Bouteille d'eau en acier inoxydable, 750 ml
Related chapters
FAQ
Do I need to pay to call an AI API from Python?
Yes, both OpenAI and Anthropic bill per token, although a few dollars of credit covers hundreds of short test calls. Set a monthly limit in the console before you start.
Which is better for Python, the OpenAI or the Anthropic SDK?
They are very similar: one client object, one create call, typed errors and automatic retries. Learn one and the other takes ten minutes. Many teams use both and pick per task.
Where should I store my API key?
In an environment variable such as OPENAI_API_KEY or ANTHROPIC_API_KEY, or in a .env file that is listed in .gitignore. Never in the source code itself.
Working with spreadsheets too? Ready-made Excel, Google Sheets and Power BI templates are at NextGenTemplates.com.
Chapter 43 of 48 · Python with AI: all 48 chapters



