n8n-code-python について
n8n 2.0以降のCodeノードでネイティブPythonを書くためのリファレンススキルです。ワークフローでPythonを使う作成者向けに、入力モード、サンドボックスの制限、戻り値の形式、データが気付かれずに通過する失敗例を説明します。
主な機能
- 01ネイティブPythonの入力変数とモード
- 02インポート許可リストとサンドボックス制限
- 03モード別の戻り値形式
- 04旧Pyodideコードの移行ガイド
- 05エラー動作とテスト項目
活用シーン
- 01旧Python Codeノードコードの移行
- 02ワークフロー項目のフィルタリングや変換
- 03インポート制限や戻り値エラーの調査
- 04n8n更新後の出力確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ czlonkowski/ n8n-skills --skill n8n-code-pythonインストール後、Claude Code で/n8n-code-pythonを入力して読み込まれたか確認します。
同梱ファイルCOMMON_PATTERNS.mdREADME.md
詳細
Python Code ノード(ネイティブ)
n8n 2.0 以降、Code ノードの Python はタスクランナー内でネイティブ Python として実行されます(language: "pythonNative")。以前の Pyodide による「Python(Beta)」は廃止され、それに伴い、そこで使えた n8n ヘルパーもすべてなくなりました。_input、_json、_node、_now、_today、_jmespath はすべて、現在は NameError を発生させます。古いテンプレート、フォーラムの投稿、以前のドキュメントからコピーしたコードは、たいてい正常に動作しません。
まずは JavaScript — 以前よりもいっそう重要です
ネイティブ Python で使えるのは、2 つの変数と通常の Python だけで、デフォルトではインポートもできません。json、datetime、re も使えません。n8n 固有の機能($('Node')、$jmespath、Luxon、this.helpers.httpRequest、静的データ)は JavaScript でのみ利用できます。Python は、ユーザーが明示的に指定した場合にのみ使ってください。その場合もまず、式、Edit Fields、またはネイティブノード(Crypto、Date & Time、HTML、XML)で対応できるか確認してください。n8n-code-javascript と n8n-expression-syntax の変換ゲートキーパーを参照してください。
クイックスタート
# Run Once for All Items (default mode)
return [
{"json": {"name": it["json"]["name"], "revenue": it["json"]["revenue"]}}
for it in _items
if it["json"].get("active")
]
# Run Once for Each Item
row = _item["json"]
return {"json": {**row, "name_upper": (row.get("name") or "").upper()}}
ノード設定:n8n-nodes-base.code の typeVersion 2 で、{"language": "pythonNative", "mode": "runOnceForAllItems" | "runOnceForEachItem", "pythonCode": "..."} を指定します。
入力は _items と _item のみ
| モード | 変数 | 形式 |
|---|---|---|
| Run Once for All Items | _items | 通常の dict {"json": {...}, "pairedItem": {...}} の list |
| Run Once for Each Item | _item | 通常の dict {"json": {...}, "pairedItem": {...}} 1 つ |
- 各変数はそれぞれのモードでのみ存在します。各アイテムモードで
_itemsを使う場合(または全アイテムモードで_itemを使う場合)、NameErrorが発生します。 - dict アクセスのみです。
it["json"]["name"]またはit["json"].get("name")を使います。it.json.nameはAttributeError: 'dict' object has no attribute 'json'を発生させます。 - ほかのノードにはアクセスできません。
_nodeや$('Node')に相当するものはありません。別のブランチのデータが必要な場合は、先に Merge で取り込むか、JavaScript で読み取ってください。 - Webhook のペイロードは
["body"]の下にあります:_items[0]["json"].get("body", {}).get("email")。 - バイナリデータについてはここでは扱いません。バイナリの読み書きには JavaScript を使ってください(n8n-binary-and-data を参照)。
- pairedItem:
_items/_itemを返すと、そのまま保持されます。新しい dict を作成し、後続の処理で$('Node').itemを使う場合は、返す各アイテムに"pairedItem": {"item": i}を追加してください。ネイティブ Python ではまだ検証されていないため、これに依存する前にテスト実行してください。 - キーがない場合:
.get(key, default)を優先してください。row["missing"]はKeyErrorを発生させます。
レガシーコードの移行表:
| レガシー(Pyodide) | ネイティブ |
|---|---|
_input.all() | _items |
_input.first()["json"] | _items[0]["json"](if _items でガード) |
_input.item / _json | _item / _item["json"] |
_node["X"] | 利用不可:上流で Merge するか、JS を使用 |
_now、_today | 利用不可:Edit Fields から {{ $now.toISO() }} を渡すか、JS を使用 |
_jmespath(data, q) | 利用不可:式内の $jmespath を使うか、内包表記を使用 |
item.json.field | item["json"]["field"] |
インポート:デフォルトではブロックされています
すべての import(標準ライブラリとサードパーティ製)は、コードの実行前に許可リストと照合されます。デフォルトの許可リストは空なので、import json でさえノード全体が拒否されます:
Security violations detected
Line 1: Import of standard library module 'json' is disallowed. Allowed stdlib modules: none
- n8n Cloud: インポートは一切できません。
- セルフホスト: 管理者はタスクランナーの設定でモジュールを許可リストに追加できます(n8n-self-hosting →
TASK_RUNNERS.mdを参照)。そのため、json、datetime、reが使えるインスタンスもあれば、ほとんど使えないインスタンスもあります。 - インポートしないコードを基本にします。 インポートが本当に役立つ場合は、まず確認してください。テスト用のノードで
import jsonとreturn [{"json": {"ok": True}}]を実行するか、ユーザーに尋ねてください。決して使えると決めつけないでください。 - インポートなしで対応するには、上流で JSON 文字列を解析します(Edit Fields で
{{ JSON.parse($json.payload) }})。日付の計算には Date & Time ノードか、式内の Luxon を使います。ISO-8601 文字列は、通常の文字列としても正しく比較・ソートできます。ハッシュ化には Crypto ノードを使います。 requests、pandas、numpyは、管理者がカスタムランナーイメージを構築していない限り、使用できません。HTTP には HTTP Request ノードを使います。
サンドボックスの制限(インポートなしでも失敗します)
| 記述するコード | 発生すること | 代わりに使うもの |
|---|---|---|
eval、exec、compile、open、input、type、getattr、setattr、hasattr、vars、dir、globals、locals、object、memoryview、breakpoint | NameError: name 'type' is not defined(実行時) | isinstance(x, dict)、key in d / d.get(key) |
class Foo: ... | __build_class__ not found(実行時) | dict と関数 |
x.__class__、"{0.__class__}".format(x)、__import__("json") | Security violations detected(実行前にノード全体が拒否されます) | — |
関数内の global counter | コードはラッパー関数内で実行されるため、NameError: name 'counter' is not defined | nonlocal counter |
それ以外の通常の Python 機能はすべて動作します(検証済み):内包表記、ジェネレーター、ラムダ、クロージャ、再帰、try / except、f 文字列 / .format() / %、sorted / min / max / sum / any / all / enumerate / zip / round、集合、isinstance、print()(出力はブラウザーのコンソールに表示されます)。
戻り値の形式(検証済み)
n8n 2.38.5 で確認されています。以下の自動ラップとパススルーの動作は文書化されておらず、今後のリリースで変更される可能性があります。n8n をアップグレードした後は、テスト実行で再確認してください。
Run Once for All Items
| 戻り値 | 結果 |
|---|---|
[{"json": {...}}, ...] | 標準形式、N 個のアイテム |
[{...}, ...](通常の dict) | json の下に自動でラップされ、N 個のアイテム |
{"json": {...}} または単一の通常の dict | 1 個のアイテム |
_items(その場で変更) | 変更内容を反映したパススルー |
None / return なし | エラー Cannot read properties of null (reading 'json') |
Run Once for Each Item
| 戻り値 | 結果 |
|---|---|
{"json": {...}}、通常の dict、または _item | 1 個のアイテム |
None | アイテムが破棄されます(組み込みフィルター) |
| リスト | エラー A 'json' property isn't a dictionary [item 0] |
出力時の値変換: tuple はリストになり、set は文字列 "{1, 2}" になり、datetime は str(dt)(ISO 形式ではなく "2026-09-16 10:18:00.025792")になります。明示的に変換してください(sorted(s)、dt.isoformat())。
全アイテムモードでは明示的な [{"json": ...}] を、各アイテムモードでは明示的な {"json": ...} を使うことをおすすめします。自動ラップも機能しますが、明示的な形式にすることで、後から読む人にも意図が伝わります。
エラーと onError
単純な raise ValueError("bad row") は、そのメッセージでノードを失敗させます。ノードで
onError の継続モードが設定されている場合、3 種類の失敗はそれぞれ異なる動作をします(検証済み)。
| 失敗 | continueErrorOutput | continueRegularOutput |
|---|---|---|
実行時例外(raise、KeyError、NameError、禁止された組み込み関数) | エラー出力(main[1])に {"error": "<message>"} ✅ | メイン出力に {"error": "<message>"} |
静的な拒否(Security violations detected:import、dunder) | ノードは失敗としてマークされますが、変更されていない入力アイテムが成功出力に送られます。main[1] は空のままです | 変更されていない入力アイテムがメイン出力に送られます |
不正な戻り値の形式(各アイテムモードでリスト、全アイテムモードで None) | 同様に、変更されていない入力が成功出力に送られます | 同様です |
後の 2 つは、データが静かにすり抜ける落とし穴です。下流ノードには、コードが実行されたかのように未処理の入力が届き、実行結果も成功と表示されます。どのエラーブランチでも捕捉できません。これらを防ぐには(確認が取れていない限り import しない、正しい戻り値の形式を使う)、実際にテスト実行して Code ノードのステータスと出力を確認してください(n8n-error-handling を参照)。
その他のメッセージ:
Python runner unavailable: Python 3 is missing from this system:セルフホストのインスタンスに Python タスクランナーがありません(標準イメージには含まれていません)。これはコードではなく、インフラストラクチャの問題です。n8n-self-hosting →TASK_RUNNERS.mdを参照してください。validate_node/validate_workflowは、いくつかの Python の誤り(import requests、returnの欠落、return None)を検出します。ただし、_input/_json、ドットアクセス、ブロックされた標準ライブラリの import、dunder アクセス、クラスは検出しません。信頼できる確認方法は、テスト実行だけです。
パフォーマンス
Python Code ノードは 1 つあたり約 0.4 秒かかります(ランナーがコールド状態の場合は約 1 秒)。JS Code ノードや式と比べると、かなり時間がかかります。アイテムごとではなく、Run Once for All Items モードでリストを処理し、1 つで済む処理に小さな Python ノードをいくつも連結しないでください。
チェックリスト
- ユーザーが実際に Python を求めていますか。そうでなければ、JS、式、またはネイティブノードを使います。
- モードは変数に合っていますか。
_items(全アイテム)/_item(各アイテム)。 - dict アクセスのみを使用していますか。
_input、_json、_node、_now、_jmespathは使いません。 - このインスタンスで許可リストへの登録が確認されていない限り、
importを使っていませんか。 - クラス、
type()、getattr/hasattr、dunder を使っていませんか。globalの代わりにnonlocalを使います。 - 戻り値の形式はモードに合っていますか。セットと日時は明示的に変換します。
- 実際にテスト実行し、出力アイテムを確認しましたか(検証だけでは上記の落とし穴を検出できません)。
リファレンス
- COMMON_PATTERNS.md:import を使わないパターンを 12 個掲載。それぞれ実際の n8n インスタンスで検証済みです(フィルター、集約、グループ化、重複排除、上位 N 件、フラット化、検証、アイテムの削除、テキストレポート、安全なネストアクセス、累計、ISO タイムスタンプ)。
関連スキル
- n8n-code-javascript:Code ノードのデフォルト。n8n ヘルパーをすべて利用できます。
- n8n-expression-syntax:
$jmespath、Luxon、変換ゲートキーパーを使います。多くの場合、Code ノードより適しています。 - n8n-code-tool:AI エージェントの Custom Code Tool で Python を使用します(
_query、文字列を返します)。 - n8n-error-handling:エラー出力の接続方法と、上記のパススルーの落とし穴について説明します。
- n8n-self-hosting:Python タスクランナーの有効化と、モジュールの許可リストへの登録について説明します。