Pythonでコードを書いていると、\n\tといった「エスケープシーケンス」が思わぬところで問題を起こすことがあります。特にWindowsのファイルパスを文字列で書いたとき、意図せずエスケープシーケンスが混入してエラーになるケースは初心者がよく踏む落とし穴です。

この記事では、Pythonのエスケープシーケンスを一覧・実行例・挙動つきで体系的に解説します。さらに、Windowsパスで起きる典型的なエラーパターンと、それを回避する3つの方法を比較しながら紹介します。「どのエスケープシーケンスが何をするのか」を一度しっかり理解することで、原因不明のバグにハマる時間を大幅に減らせます。

エスケープシーケンスとは

Python escape sequence code
Python escape sequence code / Photo by Seraphfim Gallery via Pexels

エスケープシーケンスとは、バックスラッシュ(\)から始まる特殊な文字の並びで、通常の文字では表現しにくい「改行」「タブ」「引用符」などを文字列の中に埋め込むための仕組みです。

Pythonのインタープリタは文字列を解釈するとき、\に続く文字を「ただの文字」としてではなく「制御コード」として読み取ります。この自動変換こそが、意図しないエラーの原因になることがあります。

まずは代表的なエスケープシーケンスを一覧で確認しましょう。

Pythonエスケープシーケンス一覧

エスケープシーケンス意味備考
\n改行(ラインフィード)最頻出。Windowsパスで誤爆しやすい
\t水平タブWindowsパスで誤爆しやすい
\r復帰(キャリッジリターン)Windows改行コード \r\n の一部
\bバックスペースカーソルを1文字戻す
\fフォームフィード改ページ。現代では使用頻度低
\'シングルクォーテーションシングルクォート文字列内で使用
\"ダブルクォーテーションダブルクォート文字列内で使用
\\バックスラッシュ1個文字としての \ を表す
\aベル(警告音)端末のビープ音を鳴らす
\v垂直タブ現代では使用頻度低
\0ヌル文字文字列の終端(バイナリ処理で使用)
\uXXXXUnicode文字(4桁16進数)例: \u3042 → あ
\UXXXXXXXXUnicode文字(8桁16進数)Windowsパスで誤爆しやすい
\xNN16進数指定の文字例: \x41 → A
\ooo8進数指定の文字例: \101 → A

各エスケープシーケンスの挙動と実行例

一覧を見るだけではピンとこないことも多いので、それぞれの挙動を実行例で確認していきましょう。

\n(改行)

最もよく使われるエスケープシーケンスです。文字列の途中で改行を入れます。

print('1行目\n2行目\n3行目')
1行目
2行目
3行目

\nの位置で改行され、3行に分かれて表示されます。

\t(水平タブ)

文字の間にタブ幅のスペースを挿入します。表形式のデータ出力などに便利です。

print('名前\t年齢\t職業')
print('田中\t28\tエンジニア')
print('鈴木\t34\tデザイナー')
名前    年齢    職業
田中    28      エンジニア
鈴木    34      デザイナー

\r(キャリッジリターン)

カーソルを行の先頭に戻します。\rの後に続く文字が先頭から上書きされます。

print('12345\rABC')
ABC45

\rでカーソルが先頭に戻り、ABC123を上書きするためABC45と表示されます。Windowsのテキストファイルでは行末が\r\n(CRLF)になっており、ファイルを読み込んだ際に\rが余分についていることがあります。

\b(バックスペース)

カーソルを1文字分左に移動させます。端末によっては直前の文字を削除したように見えます。

print('Python\b!')
Pytho!

\bnの前に戻り、!が上書きされた結果としてPytho!と表示されます(環境によって挙動が異なる場合があります)。

\f(フォームフィード)

改ページを意味する制御文字です。現代の端末やエディタでは改行や空行として処理されることが多く、実用的な場面は少ないです。

print('ページ1\fページ2')
ページ1ページ2

Pythonの文字列内では\x0c(ASCIIコード12)として保持されますが、print()での表示は環境依存です。

\’と\”(クォーテーション)

文字列を囲む記号と同じ引用符を文字列の中に含めたいとき、エスケープします。

# シングルクォートで囲んだ文字列内にシングルクォートを入れる
print('It\'s a pen.')

# ダブルクォートで囲んだ文字列内にダブルクォートを入れる
print("彼女は\"おはよう\"と言った。")
It's a pen.
彼女は"おはよう"と言った。

なお、シングルクォートで囲むならダブルクォートはそのまま書けますし、その逆もOKです。エスケープが不要な方の引用符を使う文字列を選ぶのが可読性の高いコードの書き方です。

\(バックスラッシュ1個)

文字列の中に\(バックスラッシュ)そのものを含めたいときは、\\と2つ並べます。

print('バックスラッシュ: \\')
print('区切り文字: a\\b\\c')
バックスラッシュ: \
区切り文字: a\b\c

\uXXXXと\UXXXXXXXX(Unicode文字)

Unicode のコードポイントを直接指定して文字を埋め込めます。\uは4桁、\Uは8桁の16進数を取ります。

# \u(4桁): ひらがな「あ」のコードポイント
print('\u3042')  # あ

# \U(8桁): 絵文字
print('\U0001F600')  # 😀
あ
😀

\UはWindowsパスで特にトラブルになりやすいエスケープシーケンスです。詳しくは後述のエラーパターンで解説します。

\xNN(16進数指定)

2桁の16進数でASCIIや拡張文字を指定できます。バイナリデータ処理やネットワークプログラミングで使われます。

print('\x41\x42\x43')  # ABC
print('\x0a')          # 改行(\nと同じ)
ABC

意図せずエスケープされて起きる典型エラー集(Windowsパス編)

Pythonでエスケープシーケンスのトラブルが最も頻繁に起きるのは、Windowsのファイルパスを文字列で直書きするときです。Windowsはパスの区切り文字にバックスラッシュ(\)を使うため、フォルダ名の頭文字によっては意図せずエスケープシーケンスとして解釈されてしまいます。

パターン①:\n による誤認識(改行への変換)

最頻出のパターンです。\notepad\networkなど、nで始まるフォルダ名やファイル名が含まれているとき、\nが改行として解釈されます。

import subprocess

# \n が改行エスケープシーケンスとして処理される!
notepad_path = 'C:\Windows\System32\notepad.exe'
print(notepad_path)
C:\Windows\System32
otepad.exe

\nが改行に変換されたため、パスが途中で折れています。このパスでsubprocess.run()を呼ぶとFileNotFoundErrorになります。

FileNotFoundError: [WinError 2] 指定されたファイルが見つかりません。

パターン②:\t による誤認識(タブへの変換)

\temp\toolsなど、tで始まるパスが含まれると\tがタブ文字に変換されます。

log_path = 'D:\tools\temp\log.txt'
print(log_path)
D:	ools	emp\log.txt

\tの箇所がタブ文字になっているため、パスが崩れています。ファイルを開こうとするとFileNotFoundErrorが発生します。

パターン③:\U による SyntaxError

\UはUnicode文字の指定に使われますが、後ろに8桁の有効な16進数が続かない場合はSyntaxErrorになります。Windowsのパスで\Usersと書くと\Uと解釈され、後続の文字が16進数でないためエラーになります。

# \Users の \U がUnicodeエスケープとして解釈されSyntaxErrorになる
path = 'C:\Users\yamada\Documents\report.xlsx'
  File "sample.py", line 2
    path = 'C:\Users\yamada\Documents\report.xlsx'
                                                  ^
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes
in position 2-3: truncated \UXXXXXXXX escape

このSyntaxErrorはPythonがファイルを読み込む段階で発生するため、コードを実行する前にはじかれます。初心者が「なぜか動かない」と最も混乱するエラーの一つです。

パターン④:\a \b \f \r \v による静かなバグ

SyntaxErrorにならず、エラーも出ないまま文字列が壊れているケースもあります。\archive\a → ベル)、\backup\b → バックスペース)、\files\f → フォームフィード)などがその例です。

backup_path = 'D:\backup\archive\data.csv'
print(repr(backup_path))
'D:\x08ackup\x07rchive\\data.csv'

\bがバックスペース(\x08)に、\aがベル(\x07)に変換されています。パス文字列として渡すとFileNotFoundErrorになりますが、エラーメッセージのパスが見た目上おかしくて原因を特定しにくいのが厄介な点です。

以下に、Windowsパスで特に注意が必要なフォルダ名頭文字をまとめます。

パスに含まれる文字列解釈されるエスケープ発生するエラー・問題
\notepad, \new\n → 改行FileNotFoundError(パス崩れ)
\temp, \tools, \taro\t → タブFileNotFoundError(パス崩れ)
\Users\U → Unicode(8桁)SyntaxError
\archive\a → ベルFileNotFoundError(静かなバグ)
\backup, \bin\b → バックスペースFileNotFoundError(静かなバグ)
\files, \forms\f → フォームフィードFileNotFoundError(静かなバグ)
\reports, \root\r → キャリッジリターンFileNotFoundError(静かなバグ)
\videos, \var\v → 垂直タブFileNotFoundError(静かなバグ)

逆に言えば、\d, \e, \g, \hのようにエスケープシーケンスとして定義されていない文字が\の後に来る場合は、Python 3.12以降はSyntaxWarning(それ以前はDeprecationWarning)が出つつも現在はそのまま通りますが、将来的にSyntaxError化される予定のため、いずれにせよ後述の回避策を使うべきです。

エスケープシーケンス問題の回避策3択

Windowsパスの問題を解決するには、主に3つの方法があります。それぞれの特徴を比較しながら解説します。

回避策①:raw文字列を使う(文字列の前に r を付ける)

文字列の開始クォートの前にrを付けると、その文字列内では\がエスケープとして解釈されなくなります。最もシンプルで可読性が高い方法です。

# r を付けるだけ。バックスラッシュがそのまま文字として扱われる
log_path = r'D:\tools\temp\log.txt'
print(log_path)

with open(log_path) as f:
    print(f.read())
D:\tools\temp\log.txt
2026-08-02 10:00:00 INFO 処理を開始しました

パスが正しく表示され、プログラムも正常に動作します。raw文字列の詳細な仕組みや注意点(末尾に\を置けないなど)については、以下の記事で詳しく解説しています。

👉 【raw文字列】Pythonで文字列の前に「r」を付ける意味

回避策②:バックスラッシュを二重化する(\ に置き換える)

\\\に書き換える方法です。\\は「バックスラッシュ1個」を意味するエスケープシーケンスなので、バックスラッシュをそのまま文字として扱えます。

# すべての \ を \\ に二重化する
log_path = 'D:\\tools\\temp\\log.txt'
print(log_path)

with open(log_path) as f:
    print(f.read())
D:\tools\temp\log.txt
2026-08-02 10:00:00 INFO 処理を開始しました

動作は回避策①と同じですが、パスが長くなるほど記述量が増え、書き忘れによるミスも起きやすくなります。短いパスや、文字列の一部だけを修正したい場面では有効ですが、長いパスの場合は後述の回避策③か、raw文字列のほうが管理しやすいです。

回避策③:pathlibまたはos.path.joinでパスを組み立てる(バックスラッシュを手書きしない)

そもそもバックスラッシュを自分で書かないようにする方法です。Pythonの標準ライブラリpathlibos.path.joinを使えば、OS に合わせたパス区切り文字を自動で処理してくれます。

pathlibを使う方法(Python 3.4以降推奨)

from pathlib import Path

# パスの各要素を / で繋ぐだけ。OSに合わせて自動変換される
log_path = Path('D:/') / 'tools' / 'temp' / 'log.txt'
print(log_path)

with open(log_path) as f:
    print(f.read())
D:\tools\temp\log.txt
2026-08-02 10:00:00 INFO 処理を開始しました

pathlib.Pathでは/演算子でパスを結合できます。スラッシュ(/)を使っているためエスケープシーケンスの問題が一切起きません。また、Windowsでもmacでも同じコードが動くためポータビリティも高いです。

os.path.joinを使う方法(レガシーコードとの互換性重視時)

import os

# 各フォルダ名をカンマ区切りで渡すだけ
log_path = os.path.join('D:\\', 'tools', 'temp', 'log.txt')
print(log_path)

with open(log_path) as f:
    print(f.read())
D:\tools\temp\log.txt
2026-08-02 10:00:00 INFO 処理を開始しました

ドライブ文字(D:\\)の部分だけは\\が必要ですが、それ以降のフォルダ名はただの文字列として渡せるため、エスケープの問題を最小化できます。

3つの回避策の比較まとめ

方法書きやすさ読みやすさクロスプラットフォームおすすめ場面
raw文字列(r”)△(Windows専用パス)パスをそのままハードコードしたい時
バックスラッシュ二重化(\\)△(長いと面倒)△(Windows専用パス)短いパスや部分的な修正
pathlib / os.path.join本格的なファイル操作・複数OS対応

迷ったときはpathlibを使うのがベストプラクティスです。エスケープの問題が根本的になくなり、コードの意図も明確になります。raw文字列は素早く書きたい場面で、バックスラッシュの二重化はすでにある文字列定数を最小限の変更で直したい場面に向いています。

文字列がどのように解釈されているか確認する方法

「自分の書いた文字列にエスケープシーケンスが混入していないか?」を確認したいときは、repr()関数が役立ちます。repr()は文字列の内部表現をそのまま表示するため、エスケープシーケンスが変換されたかどうかを視覚的に確認できます。

path_bad  = 'D:\taro\new_folder'
path_raw  = r'D:\taro\new_folder'

print(repr(path_bad))
print(repr(path_raw))
'D:\taro\new_folder'
'D:\\taro\\new_folder'

path_bad\t\nが変換されてしまっている(reprの出力ではタブが\t、改行が\nというエスケープ表示のまま現れる=変換済みの証拠)のに対し、path_rawはすべてのバックスラッシュが\\として正しく保持されています。デバッグ時にrepr()を使う習慣をつけておくと、エスケープ絡みのバグを素早く発見できます。

エスケープシーケンスを意図的に活用するパターン

ここまではエスケープシーケンスが「邪魔になる」場面を中心に解説しましたが、もちろん意図的に使うと便利な場面もたくさんあります。よく使うパターンを整理します。

テキストのフォーマット出力

# \n で複数行のメッセージを一つの文字列にまとめる
message = '処理結果:\n  成功: 10件\n  失敗: 2件\n  スキップ: 1件'
print(message)
処理結果:
  成功: 10件
  失敗: 2件
  スキップ: 1件

CSVやTSVデータの生成

# \t でタブ区切りのTSV形式を生成
data = [('田中', 28, 'エンジニア'), ('鈴木', 34, 'デザイナー')]
tsv_lines = []
for name, age, job in data:
    tsv_lines.append(f'{name}\t{age}\t{job}')
print('\n'.join(tsv_lines))
田中    28      エンジニア
鈴木    34      デザイナー

プログレスバーの上書き表示

\rを使うと、同じ行を上書きし続けることでシンプルなプログレスバーを作れます。

import time

for i in range(1, 11):
    # \r で行頭に戻り、同じ行を書き換え続ける
    print(f'\r処理中... {i * 10}%', end='', flush=True)
    time.sleep(0.2)
print('\n完了!')

実行すると、同じ行に処理中... 10%処理中... 20%→…と上書き表示され、最後に「完了!」と出力されます。

まとめ

この記事では、Pythonのエスケープシーケンスについて以下の内容を解説しました。

  • エスケープシーケンス一覧\n\t\r\b\f\'\"\\\u\U\xなど、主要なものの挙動と実行例
  • Windowsパスの典型エラーパターン\n(改行)・\t(タブ)・\U(SyntaxError)・\a\b\f\r(静かなバグ)
  • 回避策3択の比較:raw文字列・バックスラッシュ二重化・pathlib/os.path.join
  • デバッグTipsrepr()で文字列の内部状態を確認する方法

エスケープシーケンスは「知っていれば防げる」バグの代表格です。特にWindowsで作業する機会が多い方は、パスを文字列で書くときの回避策(できればpathlib)を習慣にしておきましょう。raw文字列の仕組みをさらに詳しく知りたい方は、以下の記事も参考にしてください。

👉 【raw文字列】Pythonで文字列の前に「r」を付ける意味

📚 関連商品・おすすめ書籍

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

もしも

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

初心者に定番のPython入門書

Amazonで見る
徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

もしも

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

電子工作とプログラミングを同時に学べる

Amazonで見る
Python Web開発実践入門 ―― FastAPIによるWebAPI開発と非同期処理

もしも

Python Web開発実践入門 ―― FastAPIによるWebAPI開発と非同期処理

FastAPIでWebAPI開発を実践的に学ぶ

Amazonで見る

※本記事にはアフィリエイトリンクが含まれます。

ABOUT ME
やまちゃん
これまで学生と社会人を合わせて5000人以上にプログラミング学習を指導。 ゼロからイチをわかりやすく解説する専門家として活動しており、本業ではArduinoを用いたIoT開発とロボットプログラミングが専門。 Pythonを用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。