search
LoginSignup
29

More than 1 year has passed since last update.

posted at

【初心者向け】Pythonでパス設定するときに「\」が含まれていると予期せぬ動作になる

はじめに

本記事は、Windows環境でパスの設定をする場合など「\」バックスラッシュを含んだ文字列を扱う際の、注意と対処法をまとめています。
(Macはパスの区切り文字が「/」スラッシュになっていますので、パスの設定の際はとくに気にしなくても大丈夫かと思います。)

文字列に「\」バックスラッシュが含まれていると予期せぬ動作になる

例えば、下記のようにWindowsの環境でフォルダパスの指定をした際に、想定した文字列と異なる扱いになるときがあります。

dir_name = 'C:\testDir'
print(dir_name)
# 想定した文字列        > C:\testDir
# 実際に表示される文字列 > C:      estDir

なぜこのようなことが起こるかというと、windowsのパスの区切り文字である「\」バックスラッシュは、Pythonで「エスケープシーケンス」という処理に使われるからです。

「エスケープシーケンス」がどういう処理かというと、例えば文字列の中で改行をしたいとき

txt = 'ここで改行→←改行'
# print(txt)で 以下のように表示させたい
# ここで改行→
# ←改行

改行を入れたいからといってエンターを押しても、コード上で改行されてしまいエラーになってしまいます。

txt = 'ここで改行→
←改行'
# SyntaxError: EOL while scanning string literal

そこで「改行」などの特殊な文字を表すための方法が「エスケープシーケンス」です。
改行を意味する文字は、バックスラッシュ'\'と'n'を組み合わせた'\n'で表します。

txt = 'ここで改行→\n←改行'
print(txt)
# ↓表示される文字列
# ここで改行→
# ←改行

最初のパスの設定の例だと dir_name = 'C:\testDir' の\t 部分が「TAB」という文字に扱われ
Pythonで'C:[TAB]estDir'と認識され、不自然にスペースの空いた文字列になっていたのです。

対処法

そこで「\」をエスケープシーケンス用の「\」ではなく、そのまま「\」バックスラッシュという文字列として扱う方法があります。

方法1:raw文字列

文字列の最初に「そのまま」という意味の「raw」の頭文字「r」をつけます。
raw文字列と言われ、エスケープシーケンスが行われず、そのままの文字列として扱われるようになります。

# rを付けると そのままの文字列として扱われ、エスケープされない
r'C:\testDir'

# ただし最後に「\」が含まれているものは対応できない
r'C:\testDir\'
# SyntaxError: EOL while scanning string literal

方法2:「\」バックスラッシュをエスケープする

「\」も特殊な文字なので「これはバックスラッシュです」とエスケープシーケンスで表現することができます。
バックスラッシュを2つ「\\」書くとバックスラッシュとして扱われます。

# バックスラッシュを2つ「\\」書いてバックスラッシュ自体をエスケープさせる
'C:\\testDir'

方法3:「\」バックスラッシュを「/」スラッシュに書き換える

パスに対してならこの方法が一番いいと考えています。
Linux、Macのパスの区切り文字文字は「/」スラッシュになっているため、「/」に統一するよう意識すると、環境を変更したときの不具合を防止することができます。

Windowsも区切り文字「/」スラッシュで対応出来るため
「\」バックスラッシュを「/」スラッシュに書き換えて対処します。

# 「\」バックスラッシュを「/」スラッシュに書き換える
'C:/testDir'

注意点

バックスラッシュをスラッシュに書き換える際の注意として
パスを取得する関数を利用した場合、パスの区切り文字は「\」バックスラッシュになります。

以下は、'C:\testDir'で実行しているとします。

import os
# カレントディレクトリの取得(作業中のフォルダ)
current_dir = os.getcwd()
print(current_dir)
# C:\testDir 「\」バックスラッシュで取得される

この取得したパスを利用して、以降のパスを自身で設定する場合、「/」「\」が混在しないように注意が必要です。

import os
# カレントディレクトリの取得
current_dir = os.getcwd()
# 画像用フォルダを設定 「/」で続きのパスを書く
image_dir = f'{current_dir}/image'
print(image_dir)
# C:\testDir/image 「\」「/」混在

pythonの関数では、混在していても動きはしますが、別のシステムにパスを渡すときや、パスを文字列操作するときにエラーになったりします。
例)SeleniumでChromeのダウンロードフォルダを設定するとき

そこで対処法として、パスを取得する際に「\」を「/」に置き換えてから、取得するようにします。

import os
# カレントディレクトリの取得のときに区切り文字を「/」に置き換え
current_dir = os.getcwd().replace(os.sep,'/')
print(current_dir)
# C:/testDir

おわりに

ご覧いただきありがとうございました。
「\」バックスラッシュの対応方法はいろんな方法がありますが、現場や自分自身でルールを設けて統一して、不具合のない開発が出来るようにしていきましょう。

参考

エスケープシーケンスを使用する
Pythonでエスケープシーケンスを無視(無効化)するraw文字列
セパレータの取得

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
29