一覧へ

標準入出力 — stdin/stdout のリダイレクト

Python の標準入力/出力/エラーストリームを理解し、ターミナルでリダイレクトとパイプを活用する方法を学びます。

中級
|
10
|
検証済み (2026-07)
標準入出力stdinstdoutstderrリダイレクトCLI
進捗0/18 (0%)

標準入出力 — stdin/stdout のリダイレクト

このトピックを終えると

stdin、stdout、stderr の役割を説明でき、ターミナルでリダイレクト (>, <) とパイプ (|) を使用してプログラムの入出力を接続できるようになります。


3つの経路

プログラムが実行されると、オペレーティングシステムは自動的に3つの経路を開きます。

名前方向用途Python
stdin (標準入力)外部 → プログラムキーボード入力input()sys.stdin
stdout (標準出力)プログラム → 外部通常の結果print()sys.stdout
stderr (標準エラー)プログラム → 外部エラー/警告sys.stderr

通常、stdin はキーボードに、stdout と stderr は画面(ターミナル)に接続されます。


print() は stdout に書き込む

python
# hello.py
print("こんにちは") # stdout に出力
bash
$ python hello.py
こんにちは

print() は内部的に sys.stdout.write() を呼び出します。直接使用することもできます。

python
import sys
sys.stdout.write("stdout に出力\n")
sys.stderr.write("stderr に出力\n")

どちらの行も画面に表示されますが、異なる経路を通ります。この違いはリダイレクトで明らかになります。


リダイレクト — 経路をファイルに転換する

ターミナルで >< を使用すると、入出力の方向を変えることができます。

stdout をファイルに (>)

bash
$ python hello.py > output.txt

画面には何も表示されません。print() の結果が output.txt ファイルに書き込まれます。

bash
$ cat output.txt
こんにちは

>> は既存の内容に追加します。

bash
$ python hello.py >> output.txt # 既存の内容の後に追記

stdin をファイルから (<)

python
# count.py
import sys
lines = sys.stdin.readlines()
print(f"合計 {len(lines)} 行")
bash
$ python count.py < data.txt
合計 42

data.txt の内容がキーボード入力の代わりに stdin に入力されます。

stderr のみを分離する

python
# process.py
import sys
print("処理結果:成功")
sys.stderr.write("警告:一部のデータが欠落\n")
bash
$ python process.py > result.txt 2> error.txt

> は stdout のみを、2> は stderr のみをリダイレクトします。結果とエラーを別のファイルに分離できます。


パイプ — プログラムを接続する

| (パイプ) は、前のプログラムの stdout を、次のプログラムの stdin に接続します。

bash
$ cat data.csv | python process.py | python report.py > final.txt
text
cat → (stdout) → | → (stdin) → process.py → (stdout) → | → (stdin) → report.py → final.txt

各プログラムは、自分の前のプログラムから送られてくるデータのみを受け取り、処理し、結果を次のプログラムに渡します。小さなプログラムを組み合わせて複雑な処理を行う、Unix 哲学の核心です。


Python で stdin を 1 行ずつ読み取る

python
# upper.py — 入力を大文字に変換
import sys
for line in sys.stdin:
print(line.strip().upper())
bash
$ echo "hello world" | python upper.py
HELLO WORLD
$ cat names.txt | python upper.py
ALICE
BOB
CHARLIE

sys.stdin はイテラブルです。for ループで 1 行ずつ読み込むと、メモリを効率的に使用できます。


input() と stdin の関係

python
name = input("名前: ") # プロンプト → stderr? いいえ、stdout

input() は内部的に:

  1. プロンプト文字列を stdout に出力
  2. stdin から 1 行読み込んで返す

そのため、パイプと一緒に使用する際には注意が必要です。

bash
$ echo "鉄男" | python -c "name = input(); print(f'こんにちは、{name}')"
こんにちは、鉄男

パイプではプロンプトは意味がないため、CLI ツールを作成する際には input() ではなく、sys.stdin を直接読み取る方が適切です。


実際の活用例

python
# csv_filter.py — 特定の条件の行のみ出力
import sys
import csv
reader = csv.reader(sys.stdin)
header = next(reader)
print(",".join(header))
for row in reader:
if float(row[2]) > 100: # 3 番目のカラムが 100 を超える
print(",".join(row))
bash
$ cat sales.csv | python csv_filter.py > filtered.csv

stdin/stdout を使用すると、ファイル名をハードコーディングする必要がありません。どのファイルでもパイプで接続できるため、再利用性が高くなります。


パイプチェーン — UNIX 哲学

bash
# ログから ERROR のみを検索し、頻度順にソート
$ cat server.log | grep "ERROR" | sort | uniq -c | sort -rn | head -5

各プログラムが 1 つのタスクをうまく行い、パイプで接続します。Python スクリプトもこのチェーンの 1 つの環になることができます。

python
# word_count.py — 単語の頻度を計算
import sys
from collections import Counter
words = []
for line in sys.stdin:
words.extend(line.strip().split())
for word, count in Counter(words).most_common(10):
print(f"{count:>5} {word}")
bash
$ cat article.txt | python word_count.py
42 the
31 and
28 to

stderr に進行状況を出力する

python
import sys
total = 1000
for i in range(total):
# 処理ロジック...
if i % 100 == 0:
print(f"進行: {i}/{total}", file=sys.stderr)
print(f"結果: {i * 2}") # 実際の出力 → stdout
bash
$ python process.py > results.txt
進行: 0/1000 ← 画面に表示 (stderr)
進行: 100/1000
...

stdout はファイルにリダイレクトされて results.txt に保存され、stderr は引き続き画面に表示されます。進行状況メッセージとデータを出力から分離する実用的なパターンです。


重要なまとめ

構文意味
>stdout をファイルに (上書き)
>>stdout をファイルに (追記)
<ファイルを stdin に
2>stderr をファイルに
``
2>&1stderr を stdout に統合

/dev/null — 出力を破棄する

bash
# stdout を破棄 (エラーのみ表示)
$ python noisy_script.py > /dev/null
# stderr を破棄 (結果のみ表示)
$ python noisy_script.py 2> /dev/null
# 両方を破棄 (完全無音)
$ python noisy_script.py > /dev/null 2>&1

/dev/null は「ゴミ箱」です。自動化スクリプトで不要な出力を抑制する場合に使用します。

python
# Python でも同じパターン
import os, sys
if os.environ.get("QUIET"):
sys.stdout = open(os.devnull, "w")

subprocess — Python でパイプを構成する

python
import subprocess
# 外部コマンドの実行 + stdout をキャプチャ
result = subprocess.run(
["ls", "-la"],
capture_output=True,
text=True
)
print(result.stdout)
print(result.stderr)
# パイプチェーン
p1 = subprocess.Popen(["cat", "data.txt"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", "ERROR"], stdin=p1.stdout, stdout=subprocess.PIPE)
output = p2.communicate()[0].decode()

Python 内でシェルコマンドの stdin/stdout をプログラミングで接続できます。


print() は stdout、エラーメッセージは stderr。この分離を理解すると、リダイレクトとパイプが自然になります。

💬 質問・コメント

0件のコメント

ログインせずに投稿できます。ゲスト投稿は投稿者自身で編集・削除できません。

0/2000

読み込み中...