Prompt Engineering · Python · AI Code Generation

Tom Morgan Updated May 2026 ~1,100 words read No sponsorship

I’ve run roughly 400 code-generation sessions across Claude, GPT-4o, and Gemini 2.5 over the past 14 months. What separates a prompt that produces working Python immediately from one that needs six back-and-forths isn’t creativity — it’s structure. This guide shows exactly what that structure looks like.

TL;DR — What You Need to Know in 2 Minutes

  • The real problem: Vague prompts generate vague Python. “Write a web scraper” produces unusable boilerplate; a structured prompt specifying stack, error handling, and output format produces near-production code.
  • Key finding: The CRTSE framework (Context → Role → Task → Standards → Examples) consistently outperforms unstructured prompting in both correctness and security — supported by a 2025 FORGE benchmark study on 1,080 GPT-4o samples.
  • Best technique for security-sensitive code: Recursive Critiques Improvement (RCI). Ask the model to generate, then self-critique, then regenerate.
  • Honest expectation: Even well-prompted AI generates Python with security issues about 30% of the time in complex scenarios. Human review is not optional.
  • Next step: Start with the six prompt templates in §4. Adapt one to your actual task before reading further.

Most developers who are frustrated with AI-generated Python are blaming the wrong thing. The model isn’t the problem — the instruction is. Established

Think about what happens when a junior developer gets an ambiguous ticket. They produce something that technically runs but misses the actual requirement by a mile. AI behaves identically. Augment Code’s enterprise prompt guide (Jan 2026) puts it this way: think of the model as a very fast junior developer who knows syntax but doesn’t understand context. You wouldn’t hand a junior a two-word task description and expect production code.

73% of engineering teams use AI coding tools daily as of Feb 2026 Pragmatic Engineer Survey, n=15,000
55% faster task completion with Copilot (research involving 4,800 developers) QuantumRun / GitHub
80.8% SWE-bench Verified score — Claude Opus 4.6, Q1 2026 Tech-Insider
46% of developer-written code now generated by AI on average GitHub Copilot Stats 2026

The productivity gains above are real, but they depend heavily on prompt quality. My own experience matches: the sessions where I spent 90 seconds writing a careful prompt produced working code ~78% of the time on the first response. When I rushed with a one-liner, that dropped to roughly 30–35% — meaning I spent more total time iterating than if I’d just written the code myself.

Published on DEV Community in March 2026, CRTSE has become the de facto structure for developer prompts. It stands for Context, Role, Task, Standards, Examples. The sequence matters — role before task shifts the model toward higher-quality output patterns without being roleplay fluff.

Fig 1 — CRTSE Prompt Architecture

C R T S E Context Role Task Standards Examples

Recursive Critiques Improvement is slower but materially better for sensitive code. A 2025 FORGE study benchmarking prompt techniques across 1,080 GPT-4o-generated code samples found RCI outperformed zero-shot and few-shot approaches specifically for reducing Common Weakness Enumeration (CWE) vulnerabilities in Python. The method: generate → critique → regenerate. You can wire this into a single prompt or as a two-step chain.

Tip RCI doesn’t need to be elaborate. At the end of any code-generation prompt, add: “Review what you just wrote. Identify any security issues, missing error handling, or hardcoded credentials. Fix them before presenting the final version.” That single sentence does most of the heavy lifting.

The difference between a prompt that works and one that wastes 20 minutes is almost always one of six missing components. Here’s what every serious Python prompt needs, with notes on what happens when you skip each one.

Component Example What breaks without it
Python version + runtime Python 3.12, runs on AWS Lambda Gets deprecated syntax, wrong async patterns
Exact library stack httpx 0.27, pydantic v2, boto3 Mixes incompatible APIs, uses wrong method signatures
Input/output contract Takes a list of URLs, returns {url: status_code} Produces code with wrong return shape
Error handling scope Catch network timeouts, raise custom exceptions Silently swallows errors or crashes on edge cases
Negative constraints No global state, no print() for logging Gets the most common “bad” pattern for the task
Output format Single module, no classes, type-annotated Delivers an over-engineered class hierarchy nobody asked for

Negative constraints deserve extra attention. Telling the model what not to do consistently produces better output than only describing what you want. This feels counterintuitive, but it maps to how the model samples: without constraints, it defaults to the most statistically common pattern for the task, which is often a textbook example that doesn’t match production requirements.

These are real templates from my workflow, edited for clarity. Placeholders shown in [brackets]. They’re not magic — you still need to adapt them to your stack and requirements.

Prompt Template — ETL Pipeline
Act as a senior Python data engineer.

Context: I have a [CSV / Parquet / JSON] file at [path/S3 URI] with the schema [describe columns and types].

Task: Write a function that reads this file, filters rows where [condition], transforms [column] by [operation], and writes the result to [output destination].

Standards:
- Python 3.12, pandas 2.x or polars if faster
- All IO wrapped in try/except with specific exception types
- Logging via structlog, not print()
- Type annotations on all function signatures
- No global variables

Constraints: Do NOT use pd.read_csv with default dtypes — specify dtype explicitly.

Output: A single .py module, no class, just functions. Include a __main__ block for CLI testing.
Prompt Template — FastAPI Endpoint
You are a backend engineer who cares about security and performance.

Context: I'm adding a [POST/GET] /[route] endpoint to an existing FastAPI app. Auth is handled by a middleware already in place (Bearer JWT). Database is PostgreSQL via asyncpg.

Task: Write the endpoint that:
1. Validates incoming JSON against [describe shape or paste Pydantic model]
2. Queries [describe query]
3. Returns [describe response shape]
4. Returns HTTP 422 on validation failure, 404 if record missing, 500 with generic message on DB error (don't leak internals)

Standards:
- Async throughout
- Pydantic v2 models, no dict access
- SQL queries parameterized — never f-strings in queries
- No hardcoded credentials anywhere

Output: The route file only. Assume app = FastAPI() exists. No boilerplate setup.
Prompt Template — Scraper
Act as a Python scraping specialist.

Context: I need to extract [describe data] from [URL pattern]. The site uses [static HTML / JavaScript rendering — specify]. I'm running this on a server, not a local machine.

Task: Write a scraper that:
- Fetches [N] pages
- Parses [specific fields] using CSS selectors or XPath
- Respects robots.txt
- Implements retry with exponential backoff (max 3 attempts)
- Writes output to [CSV / SQLite / JSONL]

Standards:
- Use httpx + BeautifulSoup for static, or playwright for JS rendering
- Randomize user-agent and add 1–3s delay between requests
- Python 3.12

Constraints: No Scrapy unless I ask. No selenium.

Output: Runnable script, commented, with a .env template for any config values.
Prompt Template — Debug Request
I have a Python function that's failing. Here it is:

[paste function]

The error is:
[paste full traceback]

Expected behavior: [describe what it should do]
Actual behavior: [describe what's happening]

Do not rewrite the function from scratch. Identify the root cause, explain it in one sentence, then show the minimal diff needed to fix it. If there are related bugs I should know about, list them separately after the fix.

Unit tests

Prompt Template — pytest Generation
Write pytest tests for this function:

[paste function]

Requirements:
- Cover: happy path, empty input, None input, boundary values, and at least one edge case you identify that I haven't mentioned
- Use pytest.mark.parametrize for related cases
- Mock any external calls with pytest-mock
- No test should take >200ms (add @pytest.mark.timeout if needed)
- Do NOT test implementation details — only observable behavior

Return just the test file. No explanation unless a test choice is non-obvious.

Code review / refactor

Prompt Template — Refactor Review
Act as a senior Python engineer doing a code review. Be critical but specific.

Here's the function to review:
[paste code]

Review for:
1. Correctness (bugs, edge cases)
2. Performance (obvious inefficiencies)
3. Readability (naming, structure)
4. Security (if this function handles user input or external data)

Format: For each issue, write [SEVERITY: critical/major/minor], [location: line X], [problem], [fix].
After the list, show the refactored version.
Limit: flag the 5 most important issues only. I don't need nitpicks.

5. Chain Prompting for Complex Codebases

Single-prompt code generation works well for isolated functions. Once you’re touching multiple files — say, adding a feature that requires a DB migration, a new API route, and a frontend component — single prompts start breaking down. The model loses the plot around message 8–10 in a complex context. Probable

The pattern that’s working for teams in 2026: describe one entire feature, get a plan, approve the plan, then execute file by file. Skillify’s 2026 AI Python tool roundup notes that tools like Claude Code and Windsurf allow prompts like “Create a new API endpoint in routes.py, define the Pydantic model in schemas.py, and generate a migration script” — turning the AI into an execution partner rather than a suggestion engine.

Fig 2 — Chain Prompting for Multi-File Tasks

1. Feature brief Describe entire scope 2. Approve plan Review AI’s file list 3. Execute per file One prompt per module 4. RCI pass Self-review & fix

The critical step people skip is step 2. Don’t let the model jump straight to writing code from a feature description. Ask it to output a plan — which files it will create, what each function signature looks like, what the data flow is. Reviewing that costs 3 minutes and catches 80% of architectural mistakes before any code exists.

6. Security: The Inconvenient Reality

I want to be direct about something that gets glossed over in most AI coding guides. Established

A 2025 study benchmarking prompt engineering techniques for secure code generation (FORGE/IEEE) found that roughly 32.8% of Python code snippets generated by Copilot and marked as AI-generated in GitHub projects contained security issues. A separate analysis by Pearce et al. found around 40% of Copilot completions in their CWE-scenario benchmark were vulnerable.

Those numbers aren’t a reason to stop using AI for Python. They’re a reason to review. The same FORGE study found that RCI prompting meaningfully reduced vulnerability rates — but didn’t eliminate them. The practical implication: AI code generation and human security review aren’t alternatives. They’re complementary.

Security Warning Never use AI-generated Python code that handles authentication, credentials, SQL queries, or file system access without a manual review. The most common failure modes — hardcoded secrets, unparameterized SQL, missing input sanitization — are exactly the patterns models produce most confidently.

7. What Could Be Wrong

⚠ Adversarial Section — Where This Advice Can Fail
  • Library version drift. Prompts that specify library versions will produce correct code today and broken code in 18 months when APIs change. The model’s training data skews toward older library versions — always check against current docs.
  • The more complex the prompt, the more the model hallucinates. I’ve seen well-structured 12-component prompts produce code that invents nonexistent library methods. Length isn’t the same as quality.
  • RCI doesn’t work reliably on all models. It performs well on Claude 3.5+ and GPT-4o. On smaller or older models, the self-critique step often produces a re-explanation of the problem rather than an actual fix.
  • This guide is based on ~400 sessions, mostly backend Python. I haven’t systematically tested ML/data science workflows, embedded Python, or CPython C extension code. Those are different animals.
  • Prompting well is not a substitute for understanding the code. If you can’t read the output critically, you can’t trust it. AI raises the floor for people who understand Python; it doesn’t substitute for understanding.

8. Benchmarks in Context

SWE-bench Verified has become the standard for measuring AI code generation capability. Established

Model / Tool SWE-bench Verified Date Source
Claude Opus 4.6 (Claude Code) 80.8% Q1 2026 Tech-Insider
Claude Code (standalone, 2025) 72.5% 2025 Codegen.com
GPT-4 baseline (2024) ~20% 2024 CodeToDeploy

One caution here: SWE-bench tests multi-file edits against real GitHub issues. It’s a good benchmark for agentic tools. For single-function generation — which is how most developers actually use AI — the relevant metric is closer to HumanEval pass@1. GPT-4o and Claude 3.5/4 are both above 85% on HumanEval for straightforward Python functions. SWE-bench and HumanEval are measuring different things; treat them as complementary, not competing. Probable

FAQ

Which AI model is best for Python code generation in 2026?

For agentic, multi-file tasks: Claude Code (Opus 4.6, 80.8% on SWE-bench). For inline autocomplete and boilerplate: GitHub Copilot remains faster at ~28 seconds to working code for routine tasks vs ~41 seconds for Claude Code. For free or low-cost: GPT-4o mini or Gemini 2.0 Flash perform well on self-contained functions. The honest answer is it depends on the task — no single model wins everywhere.

Does the CRTSE framework work with all LLMs?

Yes, but results vary. On reasoning-capable models (Claude 3.5+, GPT-4o, Gemini 2.5 Pro) it produces a clear step-up in output quality. On smaller models it helps structure the response but the underlying capability ceiling still applies. Don’t expect CRTSE to turn a 7B model into Claude Opus.

How long should a Python prompt be?

Long enough to cover the six components in §3, short enough to stay focused. In practice, 100–300 words is the sweet spot for a single function. Longer than that and you risk context dilution — the model starts weighting earlier instructions less. For complex multi-file tasks, use chain prompting instead of a single mega-prompt.

Is AI-generated Python safe to deploy directly?

No, not for anything security-sensitive. The FORGE 2025 benchmark found meaningful vulnerability rates even with well-structured prompts. RCI helps but doesn’t eliminate the risk. Treat AI-generated code like code from an external contributor: it must pass your code review and CI/CD security checks before production.

What’s the fastest way to go from a vague idea to working Python?

Use the ETL or API template from §4, substitute your specifics, and add one RCI instruction at the end. If the output needs more than two follow-up prompts to get right, stop and rewrite the original prompt with more specificity. Iteration feels productive but is usually slower than a better initial prompt.

Can AI handle Python version migrations (e.g., 3.9 → 3.12)?

Reasonably well for syntax changes (walrus operator, match statements, structural pattern matching). Less reliably for library API changes where the model’s training data is mixed. I’ve run ~30 such migrations — the model catches obvious deprecations but misses subtle behavioral changes in stdlib modules. Always run your test suite after AI-assisted version migration. Probable

Do these techniques work in IDEs (VS Code, PyCharm) or only in chat interfaces?

The CRTSE framework and template approach work in chat interfaces (Claude.ai, ChatGPT) and in AI-native IDEs (Cursor, Windsurf, Claude Code terminal). In inline autocomplete tools like standard Copilot, you’re limited to shorter context — focus on the negative constraints and output format components, which have the highest per-word impact on output quality.

Verdict

The gap between a developer who prompts well and one who doesn’t is measurable in minutes per task — and it compounds across a week, a sprint, a year. None of this is especially complicated. The CRTSE structure, six prompt components, the RCI self-review instruction: that’s a morning’s worth of practice and you’ll have internalized it. What takes longer is developing the judgment to review AI output critically.

AI doesn’t replace Python knowledge. It amplifies it. The developers I see getting the most out of these tools are the ones who read the generated code before running it — not because they distrust AI, but because they’re curious enough to learn from it.

“The best Python prompt you’ll ever write is the one that makes the AI’s job so specific it has no room to guess wrong.”
T

Tom Morgan — Contributor, BestPrompt.art

Tested 400+ AI code-generation sessions across 14 months. Writes about prompt engineering, developer workflows, and AI tooling. Scope: primarily backend Python, B2B SaaS environments, US/EU teams. Haven’t systematically tested ML pipelines, data science, or mobile Python. No sponsorship on this article. Last updated May 2026.

© 2026 BestPrompt.art No affiliate links · No sponsorship Updated May 2026 Python 3.12 · Claude Opus 4.6 · GPT-4o

How to Generate Code With AI Prompts — Beginner to Pro

Mastering AI Code Generation: Expert Prompt Engineering Strategies for 2025

The Prompt Engineering Stack —The Mistake Costing You Results Every Single Month

The Secret Prompt Structure That Gets the Best Result (2025)

How to Write Prompts for ChatGPT Like a Pro