[解決!Python]os.path.join関数を使ってパスを結合するには:解決!Python
os.path.join関数を使って相対パスや絶対パスを結合する方法や、最後にパス区切り文字を付加する方法、Windowsのドライブ文字の扱いなどについて紹介する。
from os.path import join
# UNIX系統のOSの場合
# 相対パスの結合
result = join('foo', 'bar', 'baz.txt')
print(result) # foo/bar/baz.txt
# 絶対パスの結合
result = join('/foo', 'bar', 'baz.txt')
print(result) # /foo/bar/baz.txt
# 引数の途中に絶対パスが含まれている場合
result = join('foo', '/bar', 'baz.txt')
print(result) # /bar/baz.txt
# 引数の最後を空文字列にすると区切り文字でパスが終わる
result = join('foo', 'bar', 'baz', '')
print(result) # foo/bar/baz/
data = 'data'
start_year = 2020
end_year = 2022
for year in range(start_year, end_year+1):
for month in range(1, 13):
path = join(data, f'{year}', f'{month:02}', '')
# data/2020/01/、data/2020/02/などのパスを使って何らかの処理を行う
print(path)
# Windowsの場合
# 相対パスの結合
result = join('foo', 'bar', 'baz.txt')
print(result) # foo\bar\baz.txt
# 絶対パスの結合
result = join('\\foo', 'bar', 'baz.txt')
print(result) # \foo\bar\baz.txt
# 引数の途中に絶対パスが含まれている場合
result = join('foo', '\\bar', 'baz.txt')
print(result) # c:\bar\baz.txt
# 絶対パスの結合(ドライブ文字を含む)
result = join('c:', '\\foo', 'bar', 'baz.txt')
print(result) # c:\foo\bar\baz.txt
# ドライブ文字とパスだけを含む場合
result = join('d:', 'foo')
print(result) # d:foo
# 引数の最後を空文字列にすると区切り文字でパスが終わる
result = join('foo', 'bar', 'baz', '')
print(result) # foo\bar\baz\
data = 'data'
start_year = 2020
end_year = 2022
for year in range(start_year, end_year+1):
for month in range(1, 13):
path = join(data, f'{year}', f'{month:02}', '')
# data\2020\01\、data\2020\02\などのパスを使って何らかの処理を行う
print(path)
パスの結合
os.pathモジュールのjoin関数を使うと、パスを構成する各要素を結合できる(このとき、使用しているOSで決められているパス区切り文字がパスとパスの間に挟み込まれる)。join関数には1つ以上の文字列(またはPathオブジェクトなど)を指定する。
以下にmacOSで実行した例を示す。
result = join('foo', 'bar', 'baz.txt')
print(result) # foo/bar/baz.txt
この例では、join関数に'foo'、'bar'、'baz.txt'という3つの文字列を渡している。その結果は、これらをパス区切り文字であるスラッシュ「/」を使って結合した「foo/bar/baz.txt」となる。
Windowsでは次のようになる。
result = join('foo', 'bar', 'baz.txt')
print(result) # foo\bar\baz.txt
Windowsではパス区切り文字がバックスラッシュ「\」になっているが、それ以外は同様だ。
上の例は相対パスを結合したものだが、絶対パスであっても同様に結合できる。以下はその例だ(macOS)。
result = join('/foo', 'bar', 'baz.txt')
print(result) # /foo/bar/baz.txt
パスを結合して、絶対パスにするには最初の引数をパス区切り文字で始めるのが簡単だ。だが、引数の中に絶対パスを含めることも可能だ。この場合、その引数よりも前に置いたパス構成要素は無視され、引数に並べた絶対パス以降の要素が結合される。
result = join('foo', '/bar', 'baz.txt')
print(result) # /bar/baz.txt
この例では第2引数がスラッシュ「/」で始まっている(つまり、これは絶対パス)。そのため、第1引数は無視されて、第2引数と第3引数を結合した結果が返されている。
このことはWindowsでも同様だ。以下に例を示す。
result = join('\\foo', 'bar', 'baz.txt')
print(result) # \foo\bar\baz.txt
注意してほしいのは、Windowsにはドライブ文字があるので、上の例の結果「\foo\bar\baz.txt」はカレントドライブの絶対パスになるということだ。
絶対パスを引数の途中に置いた場合の例は次の通り。
result = join('foo', '\\bar', 'baz.txt')
print(result) # c:\bar\baz.txt
既に述べたようにWindowsのパスにはドライブ文字という要素がある。ドライブ文字を含んだ絶対パスを結合する例を以下に示す。
result = join('c:', '\\foo', 'bar', 'baz.txt')
print(result) # c:\foo\bar\baz.txt
この例ではドライブ文字を第1引数に、ルートディレクトリを第2引数に指定している。ちなみに、引数の途中でドライブ文字を指定した場合は、絶対パスを途中で指定したときと同様に、それよりも前の引数は無視される。
result = join('\\foo', 'c:', 'bar')
print(result) # c:bar
この例では第1引数にルートディレクトリを意味する「'\\foo'」(あるいは「r'\foo'」でもよいだろう)を指定しているが、その直後にドライブ文字を指定している。そのため、「'\\foo'」は無視されて「c:bar」が返されている。この「c:bar」が意味するのは「Cドライブのカレントディレクトリの下にあるbarというパス」である。「Cドライブのルートディレクトリの直下にあるbarというパス」ではないことに注意しよう。
よって、以下は「Dドライブのカレントディレクトリにあるfoo」というパスを示す。
# ドライブ文字とパスだけを含む場合
result = join('d:', 'foo')
print(result) # d:foo
パスの最後に区切り文字を含めたいときには引数の最後に空文字列を置けばよい。
# UNIX系統のOSの例
result = join('foo', 'bar', 'baz', '')
print(result) # foo/bar/baz/
# Windowsの例
result = join('foo', 'bar', 'baz', '')
print(result) # foo\bar\baz\
UNIX系統のOSとWindowsとで区切り文字が異なるが、最後にパス区切り文字が付加されていることに注目されたい。
join関数を使うと、例えばdataディレクトリの下に年ごと、月ごとにディレクトリが作成されていて、そこに何らかのファイルがあり、それらを定型処理するといった場合に以下のようなコードが書けるだろう。
data = 'data'
start_year = 2020
end_year = 2022
for year in range(start_year, end_year+1):
for month in range(1, 13):
path = join(data, f'{year}', f'{month:02}', '')
# data/2020/01/、data/2020/02/などのパスを使って何らかの処理を行う
print(path)
これを実行すると以下のように機械的にパスを自動生成できる(Windowsではパス区切り文字が異なるが同様な結果になる)。
>>> data = 'data'
>>> start_year = 2020
>>> end_year = 2022
>>> for year in range(start_year, end_year+1):
... for month in range(1, 13):
... path = join(data, f'{year}', f'{month:02}', '')
... # data/2020/01/、data/2020/02/などのパスを使って何らかの処理を行う
... print(path)
...
data/2020/01/
data/2020/02/
data/2020/03/
# ……中略……
data/2022/10/
data/2022/11/
data/2022/12/
Copyright© Digital Advantage Corp. All Rights Reserved.