Files
n8n-skills/skills/n8n-code-python/STANDARD_LIBRARY.md
czlonkowski 4077036b23 feat: Complete Skill #7 - n8n Code Python
Implements comprehensive Python Code node guidance with critical focus on "NO external libraries" limitation.

## Skill #7 - n8n Code Python

**Critical Message**: Use JavaScript for 95% of use cases.

Python in n8n has NO external libraries (no requests, pandas, numpy).

### Files Created

**Core Skill Files (6 files, 4,205 lines total)**:

1. **SKILL.md** (748 lines)
   - When to use Python vs JavaScript (95% JavaScript recommendation)
   - Critical limitation: NO external libraries
   - Mode selection (All Items vs Each Item)
   - Data access overview (_input, _json, _node)
   - Return format requirements
   - Standard library overview

2. **DATA_ACCESS.md** (702 lines)
   - _input.all() - Process all items
   - _input.first() - Get first item
   - _input.item - Current item (Each Item mode only)
   - _node["Name"] - Reference other nodes
   - Webhook body structure (data under ["body"])
   - Pattern selection guide
   - Python vs JavaScript comparison

3. **STANDARD_LIBRARY.md** (974 lines)
   - Complete reference for available modules
   - json - JSON parsing and generation
   - datetime - Date/time operations
   - re - Regular expressions
   - base64 - Encoding/decoding
   - hashlib - Hashing (MD5, SHA256)
   - urllib.parse - URL operations
   - math, random, statistics
   - What's NOT available (requests, pandas, numpy, etc.)
   - Workarounds for missing libraries

4. **COMMON_PATTERNS.md** (794 lines)
   - 10 production-tested Python patterns
   - Multi-source data aggregation
   - Regex-based filtering
   - Markdown to structured data
   - JSON object comparison
   - CRM data transformation
   - Release notes processing
   - Array transformation
   - Dictionary lookup
   - Top N filtering
   - String aggregation
   - Python vs JavaScript pattern comparison

5. **ERROR_PATTERNS.md** (601 lines)
   - Top 5 Python-specific errors with solutions
   - Error #1: ModuleNotFoundError (THE critical Python error)
   - Error #2: Empty code / missing return
   - Error #3: KeyError (use .get() instead)
   - Error #4: IndexError (check bounds first)
   - Error #5: Incorrect return format
   - Error prevention checklist
   - Quick fix reference table
   - Testing patterns

6. **README.md** (386 lines)
   - Skill metadata and activation triggers
   - "JavaScript First" recommendation prominent
   - What this skill teaches
   - File structure overview
   - Integration with other skills
   - Success metrics checklist
   - Quick reference guide
   - Common use cases
   - Limitations and workarounds
   - Best practices

**Evaluations (5 scenarios)**:

1. **eval-001-module-import-error.json**
   - Tests understanding of external library limitation
   - Scenario: ModuleNotFoundError with requests
   - Expected: Recommend JavaScript or HTTP Request node

2. **eval-002-dictionary-keyerror.json**
   - Tests safe dictionary access with .get()
   - Scenario: KeyError when accessing missing field
   - Expected: Use .get() with default values

3. **eval-003-webhook-body-gotcha.json**
   - Tests webhook data under ["body"] understanding
   - Scenario: KeyError when accessing webhook data directly
   - Expected: Access via data.get("body", {})

4. **eval-004-return-format-error.json**
   - Tests proper return format requirement
   - Scenario: Returning plain dict instead of array
   - Expected: Return [{"json": {...}}]

5. **eval-005-standard-library-usage.json**
   - Tests knowledge of available modules
   - Scenario: What modules for JSON, hashing, dates, regex
   - Expected: json, hashlib, datetime, re (standard library only)

### Key Features

**Critical Limitations Emphasized**:
- NO external libraries (no requests, pandas, numpy)
- JavaScript recommended for 95% of use cases
- Only standard library available
- ModuleNotFoundError is #1 Python error

**Python-Specific Syntax**:
- Underscore prefix: _input, _json, _node (vs $ in JavaScript)
- Dictionary access: _json["body"]["field"] (vs dot notation)
- Safe access: .get() method with defaults

**Complete Standard Library Coverage**:
- 15+ modules documented with examples
- json, datetime, re, base64, hashlib, urllib.parse
- math, random, statistics, collections
- Clear list of what's NOT available
- Workarounds for missing functionality

**Production Patterns**:
- 10 tested patterns adapted from JavaScript
- Python-specific implementations
- List comprehensions and dictionary operations
- Standard library usage examples

**Error Prevention Focus**:
- Top 5 errors cover majority of failures
- ModuleNotFoundError prominently featured
- Safe dictionary access (.get())
- Proper return format emphasized
- Error prevention checklist

### Integration

Works seamlessly with:
- **n8n Code JavaScript**: Compare approaches, know when to use which
- **n8n Expression Syntax**: Different from {{}} expressions
- **n8n MCP Tools Expert**: Validate Code node configurations
- **n8n Workflow Patterns**: Code nodes in larger workflows
- **n8n Node Configuration**: Configure mode and connections

### Statistics

- **6 skill files**: 4,205 lines total
- **5 evaluations**: Cover critical Python scenarios
- **10 patterns**: Production-tested Python code
- **15+ modules**: Standard library coverage
- **5 top errors**: Prevention and solutions

### Design Principles

1. **JavaScript First**: 95% recommendation throughout
2. **Critical Limitation**: NO external libraries emphasized everywhere
3. **Safe Patterns**: .get() for dicts, bounds checking for lists
4. **Proper Format**: [{"json": {...}}] return format
5. **Standard Library**: Complete reference with examples
6. **Error Prevention**: Top 5 errors with solutions

### Recommendation

**Use JavaScript Code node for 95% of use cases.**

Use Python only when:
- Complex Python-specific logic required
- Python standard library features needed
- Team more comfortable with Python than JavaScript

For HTTP requests, date operations, and most transformations → Use JavaScript.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en
2025-10-20 14:33:50 +02:00

18 KiB

Standard Library Reference - Python Code Node

Complete guide to available Python standard library modules in n8n Code nodes.


⚠️ Critical Limitation

NO EXTERNAL LIBRARIES AVAILABLE

Python Code nodes in n8n have ONLY the Python standard library. No pip packages.

# ❌ NOT AVAILABLE - Will cause ModuleNotFoundError
import requests      # No HTTP library!
import pandas        # No data analysis!
import numpy         # No numerical computing!
import bs4          # No web scraping!
import selenium     # No browser automation!
import psycopg2     # No database drivers!
import pymongo      # No MongoDB!
import sqlalchemy   # No ORMs!

# ✅ AVAILABLE - Standard library only
import json
import datetime
import re
import base64
import hashlib
import urllib.parse
import urllib.request
import math
import random
import statistics

Recommendation: Use JavaScript for 95% of use cases. JavaScript has more capabilities in n8n.


Available Modules

Priority 1: Most Useful (Use These)

  1. json - JSON parsing and generation
  2. datetime - Date and time operations
  3. re - Regular expressions
  4. base64 - Base64 encoding/decoding
  5. hashlib - Hashing (MD5, SHA256, etc.)
  6. urllib.parse - URL parsing and encoding

Priority 2: Moderately Useful

  1. math - Mathematical functions
  2. random - Random number generation
  3. statistics - Statistical functions
  4. collections - Specialized data structures

Priority 3: Occasionally Useful

  1. itertools - Iterator tools
  2. functools - Higher-order functions
  3. operator - Standard operators as functions
  4. string - String constants and templates
  5. textwrap - Text wrapping utilities

Module 1: json - JSON Operations

Most common module - Parse and generate JSON data.

Parse JSON String

import json

# Parse JSON string to Python dict
json_string = '{"name": "Alice", "age": 30}'
data = json.loads(json_string)

return [{
    "json": {
        "name": data["name"],
        "age": data["age"],
        "parsed": True
    }
}]

Generate JSON String

import json

# Convert Python dict to JSON string
data = {
    "users": [
        {"id": 1, "name": "Alice"},
        {"id": 2, "name": "Bob"}
    ],
    "total": 2
}

json_string = json.dumps(data, indent=2)

return [{
    "json": {
        "json_output": json_string,
        "length": len(json_string)
    }
}]

Handle JSON Errors

import json

webhook_data = _input.first()["json"]["body"]
json_string = webhook_data.get("data", "")

try:
    parsed = json.loads(json_string)
    status = "valid"
    error = None
except json.JSONDecodeError as e:
    parsed = None
    status = "invalid"
    error = str(e)

return [{
    "json": {
        "status": status,
        "data": parsed,
        "error": error
    }
}]

Pretty Print JSON

import json

# Format JSON with indentation
data = _input.first()["json"]

pretty_json = json.dumps(data, indent=2, sort_keys=True)

return [{
    "json": {
        "formatted": pretty_json
    }
}]

Module 2: datetime - Date and Time

Very common - Date parsing, formatting, calculations.

Current Date and Time

from datetime import datetime

now = datetime.now()

return [{
    "json": {
        "timestamp": now.isoformat(),
        "date": now.strftime("%Y-%m-%d"),
        "time": now.strftime("%H:%M:%S"),
        "formatted": now.strftime("%B %d, %Y at %I:%M %p")
    }
}]

Parse Date String

from datetime import datetime

date_string = "2025-01-15T14:30:00"
dt = datetime.fromisoformat(date_string)

return [{
    "json": {
        "year": dt.year,
        "month": dt.month,
        "day": dt.day,
        "hour": dt.hour,
        "weekday": dt.strftime("%A")
    }
}]

Date Calculations

from datetime import datetime, timedelta

now = datetime.now()

# Calculate future/past dates
tomorrow = now + timedelta(days=1)
yesterday = now - timedelta(days=1)
next_week = now + timedelta(weeks=1)
one_hour_ago = now - timedelta(hours=1)

return [{
    "json": {
        "now": now.isoformat(),
        "tomorrow": tomorrow.isoformat(),
        "yesterday": yesterday.isoformat(),
        "next_week": next_week.isoformat(),
        "one_hour_ago": one_hour_ago.isoformat()
    }
}]

Compare Dates

from datetime import datetime

date1 = datetime(2025, 1, 15)
date2 = datetime(2025, 1, 20)

# Calculate difference
diff = date2 - date1

return [{
    "json": {
        "days_difference": diff.days,
        "seconds_difference": diff.total_seconds(),
        "date1_is_earlier": date1 < date2,
        "date2_is_later": date2 > date1
    }
}]

Format Dates

from datetime import datetime

dt = datetime.now()

return [{
    "json": {
        "iso": dt.isoformat(),
        "us_format": dt.strftime("%m/%d/%Y"),
        "eu_format": dt.strftime("%d/%m/%Y"),
        "long_format": dt.strftime("%A, %B %d, %Y"),
        "time_12h": dt.strftime("%I:%M %p"),
        "time_24h": dt.strftime("%H:%M:%S")
    }
}]

Module 3: re - Regular Expressions

Common - Pattern matching, text extraction, validation.

Pattern Matching

import re

text = "Email: alice@example.com, Phone: 555-1234"

# Find email
email_match = re.search(r'\b[\w.-]+@[\w.-]+\.\w+\b', text)
email = email_match.group(0) if email_match else None

# Find phone
phone_match = re.search(r'\d{3}-\d{4}', text)
phone = phone_match.group(0) if phone_match else None

return [{
    "json": {
        "email": email,
        "phone": phone
    }
}]

Extract All Matches

import re

text = "Tags: #python #automation #workflow #n8n"

# Find all hashtags
hashtags = re.findall(r'#(\w+)', text)

return [{
    "json": {
        "tags": hashtags,
        "count": len(hashtags)
    }
}]

Replace Patterns

import re

text = "Price: $99.99, Discount: $10.00"

# Remove dollar signs
cleaned = re.sub(r'\$', '', text)

# Replace multiple spaces with single space
normalized = re.sub(r'\s+', ' ', cleaned)

return [{
    "json": {
        "original": text,
        "cleaned": cleaned,
        "normalized": normalized
    }
}]

Validate Format

import re

email = _input.first()["json"]["body"].get("email", "")

# Email validation pattern
email_pattern = r'^[\w.-]+@[\w.-]+\.\w+$'
is_valid = bool(re.match(email_pattern, email))

return [{
    "json": {
        "email": email,
        "valid": is_valid
    }
}]

Split on Pattern

import re

text = "apple,banana;orange|grape"

# Split on multiple delimiters
items = re.split(r'[,;|]', text)

# Clean up whitespace
items = [item.strip() for item in items]

return [{
    "json": {
        "items": items,
        "count": len(items)
    }
}]

Module 4: base64 - Encoding/Decoding

Common - Encode binary data, API authentication.

Encode String to Base64

import base64

text = "Hello, World!"

# Encode to base64
encoded_bytes = base64.b64encode(text.encode('utf-8'))
encoded_string = encoded_bytes.decode('utf-8')

return [{
    "json": {
        "original": text,
        "encoded": encoded_string
    }
}]

Decode Base64 to String

import base64

encoded = "SGVsbG8sIFdvcmxkIQ=="

# Decode from base64
decoded_bytes = base64.b64decode(encoded)
decoded_string = decoded_bytes.decode('utf-8')

return [{
    "json": {
        "encoded": encoded,
        "decoded": decoded_string
    }
}]

Basic Auth Header

import base64

username = "admin"
password = "secret123"

# Create Basic Auth header
credentials = f"{username}:{password}"
encoded = base64.b64encode(credentials.encode('utf-8')).decode('utf-8')
auth_header = f"Basic {encoded}"

return [{
    "json": {
        "authorization": auth_header
    }
}]

Module 5: hashlib - Hashing

Common - Generate checksums, hash passwords, create IDs.

MD5 Hash

import hashlib

text = "Hello, World!"

# Generate MD5 hash
md5_hash = hashlib.md5(text.encode('utf-8')).hexdigest()

return [{
    "json": {
        "original": text,
        "md5": md5_hash
    }
}]

SHA256 Hash

import hashlib

data = _input.first()["json"]["body"]
text = data.get("password", "")

# Generate SHA256 hash (more secure than MD5)
sha256_hash = hashlib.sha256(text.encode('utf-8')).hexdigest()

return [{
    "json": {
        "hashed": sha256_hash
    }
}]

Generate Unique ID

import hashlib
from datetime import datetime

# Create unique ID from multiple values
unique_string = f"{datetime.now().isoformat()}-{_json.get('user_id', 'unknown')}"
unique_id = hashlib.sha256(unique_string.encode('utf-8')).hexdigest()[:16]

return [{
    "json": {
        "id": unique_id,
        "generated_at": datetime.now().isoformat()
    }
}]

Module 6: urllib.parse - URL Operations

Common - Parse URLs, encode parameters.

Parse URL

from urllib.parse import urlparse

url = "https://example.com/path?key=value&foo=bar#section"

parsed = urlparse(url)

return [{
    "json": {
        "scheme": parsed.scheme,      # "https"
        "netloc": parsed.netloc,      # "example.com"
        "path": parsed.path,          # "/path"
        "query": parsed.query,        # "key=value&foo=bar"
        "fragment": parsed.fragment    # "section"
    }
}]

URL Encode Parameters

from urllib.parse import urlencode

params = {
    "name": "Alice Smith",
    "email": "alice@example.com",
    "message": "Hello, World!"
}

# Encode parameters for URL
encoded = urlencode(params)

return [{
    "json": {
        "query_string": encoded,
        "full_url": f"https://api.example.com/submit?{encoded}"
    }
}]

Parse Query String

from urllib.parse import parse_qs

query_string = "name=Alice&age=30&tags=python&tags=n8n"

# Parse query string
params = parse_qs(query_string)

return [{
    "json": {
        "name": params.get("name", [""])[0],
        "age": int(params.get("age", ["0"])[0]),
        "tags": params.get("tags", [])
    }
}]

URL Encode/Decode Strings

from urllib.parse import quote, unquote

text = "Hello, World! 你好"

# URL encode
encoded = quote(text)

# URL decode
decoded = unquote(encoded)

return [{
    "json": {
        "original": text,
        "encoded": encoded,
        "decoded": decoded
    }
}]

Module 7: math - Mathematical Operations

Moderately useful - Advanced math functions.

Basic Math Functions

import math

number = 16.7

return [{
    "json": {
        "ceiling": math.ceil(number),      # 17
        "floor": math.floor(number),       # 16
        "rounded": round(number),          # 17
        "square_root": math.sqrt(16),      # 4.0
        "power": math.pow(2, 3),          # 8.0
        "absolute": math.fabs(-5.5)       # 5.5
    }
}]

Trigonometry

import math

angle_degrees = 45
angle_radians = math.radians(angle_degrees)

return [{
    "json": {
        "sine": math.sin(angle_radians),
        "cosine": math.cos(angle_radians),
        "tangent": math.tan(angle_radians),
        "pi": math.pi,
        "e": math.e
    }
}]

Logarithms

import math

number = 100

return [{
    "json": {
        "log10": math.log10(number),     # 2.0
        "natural_log": math.log(number), # 4.605...
        "log2": math.log2(number)        # 6.644...
    }
}]

Module 8: random - Random Numbers

Moderately useful - Generate random data, sampling.

Random Numbers

import random

return [{
    "json": {
        "random_float": random.random(),           # 0.0 to 1.0
        "random_int": random.randint(1, 100),      # 1 to 100
        "random_range": random.randrange(0, 100, 5) # 0, 5, 10, ..., 95
    }
}]

Random Choice

import random

colors = ["red", "green", "blue", "yellow"]
users = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]

return [{
    "json": {
        "random_color": random.choice(colors),
        "random_user": random.choice(users)
    }
}]

Shuffle List

import random

items = [1, 2, 3, 4, 5]
shuffled = items.copy()
random.shuffle(shuffled)

return [{
    "json": {
        "original": items,
        "shuffled": shuffled
    }
}]

Random Sample

import random

items = list(range(1, 101))

# Get 10 random items without replacement
sample = random.sample(items, 10)

return [{
    "json": {
        "sample": sample,
        "count": len(sample)
    }
}]

Module 9: statistics - Statistical Functions

Moderately useful - Calculate stats from data.

Basic Statistics

import statistics

numbers = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

return [{
    "json": {
        "mean": statistics.mean(numbers),           # 55.0
        "median": statistics.median(numbers),       # 55.0
        "mode": statistics.mode([1, 2, 2, 3]),     # 2
        "stdev": statistics.stdev(numbers),        # 30.28...
        "variance": statistics.variance(numbers)   # 916.67...
    }
}]

Aggregate from Items

import statistics

all_items = _input.all()

# Extract amounts
amounts = [item["json"].get("amount", 0) for item in all_items]

if amounts:
    return [{
        "json": {
            "count": len(amounts),
            "total": sum(amounts),
            "average": statistics.mean(amounts),
            "median": statistics.median(amounts),
            "min": min(amounts),
            "max": max(amounts),
            "range": max(amounts) - min(amounts)
        }
    }]
else:
    return [{"json": {"error": "No data"}}]

Workarounds for Missing Libraries

HTTP Requests (No requests library)

# ❌ Can't use requests library
# import requests  # ModuleNotFoundError!

# ✅ Use HTTP Request node instead
# Add HTTP Request node BEFORE Code node
# Access the response in Code node

response_data = _input.first()["json"]

return [{
    "json": {
        "status": response_data.get("status"),
        "data": response_data.get("body"),
        "processed": True
    }
}]

Data Processing (No pandas)

# ❌ Can't use pandas
# import pandas as pd  # ModuleNotFoundError!

# ✅ Use Python's built-in list comprehensions
all_items = _input.all()

# Filter
active_items = [
    item for item in all_items
    if item["json"].get("status") == "active"
]

# Group by
from collections import defaultdict
grouped = defaultdict(list)

for item in all_items:
    category = item["json"].get("category", "other")
    grouped[category].append(item["json"])

# Aggregate
import statistics
amounts = [item["json"].get("amount", 0) for item in all_items]
total = sum(amounts)
average = statistics.mean(amounts) if amounts else 0

return [{
    "json": {
        "active_count": len(active_items),
        "grouped": dict(grouped),
        "total": total,
        "average": average
    }
}]

Database Operations (No drivers)

# ❌ Can't use database drivers
# import psycopg2  # ModuleNotFoundError!
# import pymongo   # ModuleNotFoundError!

# ✅ Use n8n database nodes instead
# Add Postgres/MySQL/MongoDB node BEFORE Code node
# Process results in Code node

db_results = _input.first()["json"]

return [{
    "json": {
        "record_count": len(db_results) if isinstance(db_results, list) else 1,
        "processed": True
    }
}]

Complete Standard Library List

Available (commonly useful):

  • json
  • datetime, time
  • re
  • base64
  • hashlib
  • urllib.parse, urllib.request, urllib.error
  • math
  • random
  • statistics
  • collections (defaultdict, Counter, namedtuple)
  • itertools
  • functools
  • operator
  • string
  • textwrap

Available (less common):

  • os.path (path operations only)
  • copy
  • typing
  • enum
  • decimal
  • fractions

NOT Available (external libraries):

  • requests (HTTP)
  • pandas (data analysis)
  • numpy (numerical computing)
  • bs4/beautifulsoup4 (HTML parsing)
  • selenium (browser automation)
  • psycopg2, pymongo, sqlalchemy (databases)
  • flask, fastapi (web frameworks)
  • pillow (image processing)
  • openpyxl, xlsxwriter (Excel)

Best Practices

1. Use Standard Library When Possible

# ✅ GOOD: Use standard library
import json
import datetime
import re

data = _input.first()["json"]
processed = json.loads(data.get("json_string", "{}"))

return [{"json": processed}]

2. Fall Back to n8n Nodes

# For operations requiring external libraries,
# use n8n nodes instead:
# - HTTP Request for API calls
# - Postgres/MySQL for databases
# - Extract from File for parsing

# Then process results in Code node
result = _input.first()["json"]
return [{"json": {"processed": result}}]

3. Combine Multiple Modules

import json
import base64
import hashlib
from datetime import datetime

# Combine modules for complex operations
data = _input.first()["json"]["body"]

# Hash sensitive data
user_id = hashlib.sha256(data.get("email", "").encode()).hexdigest()[:16]

# Encode for storage
encoded_data = base64.b64encode(json.dumps(data).encode()).decode()

return [{
    "json": {
        "user_id": user_id,
        "encoded_data": encoded_data,
        "timestamp": datetime.now().isoformat()
    }
}]

Summary

Most Useful Modules:

  1. json - Parse/generate JSON
  2. datetime - Date operations
  3. re - Regular expressions
  4. base64 - Encoding
  5. hashlib - Hashing
  6. urllib.parse - URL operations

Critical Limitation:

  • NO external libraries (requests, pandas, numpy, etc.)

Recommended Approach:

  • Use JavaScript for 95% of use cases
  • Use Python only when specifically needed
  • Use n8n nodes for operations requiring external libraries

See Also: