【Python標準ライブラリ入門 第4回】ファイル・ディレクトリ操作の達人になろう!osモジュール徹底ガイド

「プログラムから新しいフォルダを作ったり、ファイルの一覧を取得したりしたい!」
「ファイルの存在を確認してから処理を行いたいんだけど、どうすればいい?」
「Pythonスクリプトが今どこで実行されているか知りたい!」

こんにちは! Python標準ライブラリ探検隊、隊長のPythonistaです! 前回はjsonモジュールを使って、プログラム間でデータをやり取りしたり、設定を保存したりする方法を学びましたね。データの扱いがグッと楽になったのではないでしょうか。

シリーズ第4回の今回は、あなたのPythonプログラムがコンピュータのファイルシステムやオペレーティングシステム(OS)と直接対話するための強力な道具箱、osモジュールを徹底解説します! osモジュールを使えば、ディレクトリ(フォルダ)の作成や削除、ファイル名の変更、パスの操作、環境変数の取得など、OSレベルの様々な操作をPythonから行うことができます。ファイル整理の自動化から、より高度なシステム管理タスクまで、osモジュールはあなたのプログラミングの可能性を大きく広げてくれます。さあ、PythonでOSと友達になりましょう!その他の投稿はこちら


1. osモジュールとは? なぜ重要?

osモジュールは、Pythonでオペレーティングシステムが提供する様々な機能を利用するためのインターフェースを提供する標準ライブラリです。このモジュールを通じて、プログラムは実行されているOS環境と対話し、ファイルシステムの操作やプロセス管理など、多岐にわたるタスクを実行できます。

osモジュールの主な役割と重要性:

  • ファイルシステム操作: ファイルやディレクトリの作成、削除、名前変更、一覧取得など、ファイルシステムに対する基本的な操作を網羅しています。
  • パス操作: ファイルやディレクトリの場所を示す「パス」文字列を安全かつOSに依存しない形で組み立てたり、分割したり、情報を取得したりできます(これにはos.pathサブモジュールがよく使われます)。
  • 環境変数の利用: OSに設定されている環境変数を読み取ったり、設定したりできます。
  • プロセスの管理: 新しいプロセスを起動したり、現在のプロセスIDを取得したりといった操作も可能です(今回は主にファイル・ディレクトリ操作に焦点を当てます)。
  • プラットフォーム間の互換性: Windows, macOS, Linuxなど、異なるOS間でも同じように動作するポータブルなコードを書く手助けをしてくれます(ただし、一部OS固有の機能も存在します)。

osモジュールは非常に多機能ですが、この記事では特に初心者がよく使う、ファイルとディレクトリの操作、そしてパスの扱いに焦点を当てて解説していきます。


2. osモジュールの基本的な使い方

まずは、osモジュールをインポートし、基本的な操作方法を見ていきましょう。

2.1. モジュールのインポート

osモジュールを利用するには、まずインポートします。

import os

2.2. カレントワーキングディレクトリ (現在の作業場所) の操作

プログラムを実行している現在のディレクトリ(フォルダ)をカレントワーキングディレクトリ(CWD)と呼びます。ファイル操作を行う際、相対パスはこのCWDを基準に解釈されます。

  • os.getcwd(): 現在のカレントワーキングディレクトリのパスを文字列として取得します (get current working directory)。
  • os.chdir(path): カレントワーキングディレクトリを指定したpathに変更します (change directory)。
import os

# 現在のカレントワーキングディレクトリを取得して表示
current_dir = os.getcwd()
print(f"現在のディレクトリ: {current_dir}")

# 新しいディレクトリを作成してみる (後で詳しく解説)
if not os.path.exists("test_dir"):
    os.mkdir("test_dir")

# カレントワーキングディレクトリを変更
try:
    os.chdir("test_dir")
    print(f"変更後のディレクトリ: {os.getcwd()}")

    # 元のディレクトリに戻る (パスは環境によって調整してください)
    # os.chdir("..") # 一つ上の階層へ
    os.chdir(current_dir) # 元のパスを覚えておいて戻るのが確実
    print(f"元のディレクトリに戻りました: {os.getcwd()}")

except FileNotFoundError:
    print("エラー: 指定されたディレクトリが見つかりません。")
except Exception as e:
    print(f"エラーが発生しました: {e}")
finally:
    # 作成したテストディレクトリを削除 (中身が空である必要あり)
    if os.path.exists("test_dir") and not os.listdir("test_dir"):
        os.rmdir("test_dir")

注意: os.chdir()で存在しないパスを指定するとFileNotFoundErrorが発生します。

2.3. ディレクトリ(フォルダ)の操作

  • os.mkdir(path): 指定したpathに新しいディレクトリを1つ作成します。もし親ディレクトリが存在しない場合や、指定したパスが既に存在する場合はエラーになります。
  • os.makedirs(path, exist_ok=False): 指定したpathにディレクトリを再帰的に作成します。つまり、途中の親ディレクトリが存在しなくても、それらも一緒に作成してくれます。exist_ok=Trueにすると、指定したディレクトリが既に存在していてもエラーになりません(デフォルトはFalseでエラー)。
  • os.listdir(path='.'): 指定したpath(デフォルトはカレントディレクトリ)に含まれるファイルとディレクトリの名前の一覧をリストとして返します。.(カレントディレクトリ)や..(親ディレクトリ)も含まれることがあります。
  • os.rmdir(path): 指定したpath空のディレクトリを削除します。ディレクトリ内にファイルや他のディレクトリがあるとOSErrorが発生します。
  • os.removedirs(path): 指定したpathから可能な限り親ディレクトリを再帰的に削除しようとします。つまり、指定したディレクトリが空なら削除し、その親ディレクトリも空になればそれも削除…という動作を繰り返します。
import os

# 新しいディレクトリの作成
dir_name_single = "my_new_folder"
if not os.path.exists(dir_name_single):
    os.mkdir(dir_name_single)
    print(f"'{dir_name_single}' を作成しました。")
else:
    print(f"'{dir_name_single}' は既に存在します。")

dir_name_recursive = "parent_folder/child_folder"
os.makedirs(dir_name_recursive, exist_ok=True) # exist_ok=Trueで安心
print(f"'{dir_name_recursive}' を作成しました(または既に存在)。")

# ディレクトリ内のリスト表示
print(f"\nカレントディレクトリの内容: {os.listdir('.')}")
if os.path.exists("parent_folder"):
    print(f"parent_folderの内容: {os.listdir('parent_folder')}")


# ディレクトリの削除 (順番に注意)
if os.path.exists(dir_name_recursive):
    os.rmdir(dir_name_recursive) # child_folderをまず削除
    print(f"'{dir_name_recursive}' を削除しました。")
if os.path.exists("parent_folder"):
    os.rmdir("parent_folder") # 次にparent_folderを削除
    print(f"'parent_folder' を削除しました。")
if os.path.exists(dir_name_single):
    os.rmdir(dir_name_single)
    print(f"'{dir_name_single}' を削除しました。")

注意: ディレクトリの削除は慎重に行ってください。特にos.removedirs()は意図しない親ディレクトリまで削除してしまう可能性があるので注意が必要です。

2.4. ファイルの操作(存在確認、削除、名前変更など)

osモジュール自体はファイルの内容を直接読み書きする機能は持ちませんが(それはopen()関数の役割です)、ファイルシステムレベルでの操作を提供します。特にos.pathサブモジュールが重要です。

  • os.path.exists(path): 指定したpathのファイルまたはディレクトリが存在すればTrue、しなければFalseを返します。処理を行う前の存在確認に非常に重要です。
  • os.path.isfile(path): 指定したpathがファイルであり、かつ存在すればTrueを返します。
  • os.path.isdir(path): 指定したpathがディレクトリであり、かつ存在すればTrueを返します。
  • os.remove(path) または os.unlink(path): 指定したpathのファイルを削除します。ディレクトリは削除できません。
  • os.rename(src, dst): ファイルまたはディレクトリの名前をsrc(元の名前)からdst(新しい名前)に変更します。同じファイルシステム内であれば、移動(dstにディレクトリパスを含める)も可能です。
import os

file_name = "sample_file.txt"

# テスト用ファイルの作成
with open(file_name, 'w', encoding='utf-8') as f:
    f.write("これはテストファイルです。\n")

# ファイルの存在確認
if os.path.exists(file_name):
    print(f"\n'{file_name}' は存在します。")
    if os.path.isfile(file_name):
        print(f"'{file_name}' はファイルです。")
else:
    print(f"'{file_name}' は存在しません。")

# ファイル名の変更
new_file_name = "renamed_sample_file.txt"
if os.path.exists(file_name):
    os.rename(file_name, new_file_name)
    print(f"'{file_name}' を '{new_file_name}' に変更しました。")

# ファイルの削除
if os.path.exists(new_file_name):
    os.remove(new_file_name)
    print(f"'{new_file_name}' を削除しました。")

注意: os.remove()によるファイルの削除は元に戻せません。重要なファイルを誤って削除しないよう、十分注意してください。


3. パス操作の基本:os.pathサブモジュール

ファイルやディレクトリの場所を示す「パス」文字列は、OSによって区切り文字(Windowsでは\、LinuxやmacOSでは/)が異なります。os.pathサブモジュールを使うと、これらのOS間の違いを吸収し、安全かつポータブルなパス操作が可能になります。

  • os.path.join(*paths): 1つ以上のパス要素を、OSに適した区切り文字で結合して新しいパス文字列を返します。パス文字列を自前で+で連結する代わりに、必ずこれを使うようにしましょう。
  • os.path.split(path): 指定したパスを、最後の区切り文字でディレクトリ部分 (head) とファイル名/末尾ディレクトリ名部分 (tail) に分割し、(head, tail)のタプルで返します。
  • os.path.basename(path): パス文字列からファイル名または末尾のディレクトリ名だけを取り出します (os.path.split(path)[1] と同等)。
  • os.path.dirname(path): パス文字列からディレクトリ部分だけを取り出します (os.path.split(path)[0] と同等)。
  • os.path.abspath(path): 相対パスを絶対パス(ルートディレクトリからの完全なパス)に変換して返します。
  • os.path.splitext(path): パス文字列を、拡張子とその前の部分に分割し、(root, ext)のタプルで返します。拡張子部分にはドット(.)も含まれます。
import os

# パスの結合 (OSに合わせた区切り文字が使われる)
path1 = os.path.join("folder1", "folder2", "file.txt")
print(f"\n結合されたパス: {path1}") # Windowsなら folder1\folder2\file.txt

full_path = "/usr/local/bin/python_script.py" # Linux/macOS風のパス
# full_path_win = "C:\\Users\\YourName\\Documents\\script.py" # Windows風

# パスの分割
dir_part, file_part = os.path.split(full_path)
print(f"ディレクトリ部分: {dir_part}")
print(f"ファイル/末尾部分: {file_part}")

# ベース名とディレクトリ名の取得
base_name = os.path.basename(full_path)
dir_name = os.path.dirname(full_path)
print(f"ベース名: {base_name}")
print(f"ディレクトリ名: {dir_name}")

# 絶対パスの取得 (カレントディレクトリからの相対パスで試す)
relative_path = "my_file.txt"
absolute_path = os.path.abspath(relative_path)
print(f"'{relative_path}' の絶対パス: {absolute_path}")

# 拡張子の分割
file_path_with_ext = "document.v1.docx"
root_name, extension = os.path.splitext(file_path_with_ext)
print(f"ファイル名本体: {root_name}")
print(f"拡張子: {extension}") # .docx

4. 環境変数の操作

環境変数は、OSがプログラムの実行環境に関する情報(例: ユーザー名、プログラムの検索パスなど)を保持するために使われます。

  • os.environ: 全ての環境変数を保持する辞書のようなオブジェクトです。os.environ['変数名']のようにして値にアクセスできます。存在しないキーを指定するとKeyErrorが発生します。
  • os.getenv(key, default=None): 指定したkey(環境変数名)の値を取得します。もしその環境変数が存在しない場合、defaultで指定した値(デフォルトはNone)を返します。KeyErrorを避けたい場合に便利です。
import os

# 全ての環境変数を表示 (非常に多く出力されるので注意)
# print("\n--- 全ての環境変数 ---")
# for key, value in os.environ.items():
#     print(f"{key} = {value[:50]}{'...' if len(value) > 50 else ''}") # 値が長い場合は省略

# 特定の環境変数を取得 (例: PATH)
path_env = os.getenv("PATH")
if path_env:
    print(f"\nPATH環境変数 (最初の100文字): {path_env[:100]}...")
else:
    print("\nPATH環境変数は設定されていません。")

# 存在しないかもしれない環境変数を取得
my_custom_var = os.getenv("MY_CUSTOM_VARIABLE", "デフォルト値")
print(f"MY_CUSTOM_VARIABLE: {my_custom_var}")

# os.environを使ってアクセス (存在しないとエラー)
try:
    username = os.environ['USERNAME'] # Windowsの場合。macOS/Linuxなら'USER'や'LOGNAME'など
    print(f"現在のユーザー名 (USERNAME): {username}")
except KeyError:
    try:
        username = os.environ['USER']
        print(f"現在のユーザー名 (USER): {username}")
    except KeyError:
        print("ユーザー名を取得できませんでした。")

プログラムの設定を環境変数経由で行うこともよくあります(例: APIキーの隠蔽など)。


5. 実践的な例:osモジュールを使ってみよう

例1:カレントディレクトリ内のPythonファイル(.py)だけを一覧表示する

import os

print("\n--- カレントディレクトリ内のPythonファイル ---")
py_files = []
for item in os.listdir('.'): # カレントディレクトリをリスト
    if os.path.isfile(item) and item.endswith(".py"): # ファイルであり、かつ拡張子が.py
        py_files.append(item)

if py_files:
    for py_file in py_files:
        print(py_file)
else:
    print("Pythonファイルは見つかりませんでした。")

例2:指定した名前のディレクトリを作成し、その中に連番ファイルを作成する

import os

output_dir = "output_files"
os.makedirs(output_dir, exist_ok=True) # ディレクトリがなければ作成

for i in range(1, 4): # file_1.txt, file_2.txt, file_3.txt を作成
    file_name = f"file_{i}.txt"
    file_path = os.path.join(output_dir, file_name)
    with open(file_path, 'w', encoding='utf-8') as f:
        f.write(f"これは {file_name} の内容です。\n")
    print(f"'{file_path}' を作成しました。")

print(f"\n'{output_dir}' の中身: {os.listdir(output_dir)}")

# 後片付け (注意して実行)
# for i in range(1, 4):
#     file_name = f"file_{i}.txt"
#     file_path = os.path.join(output_dir, file_name)
#     if os.path.exists(file_path): os.remove(file_path)
# if os.path.exists(output_dir): os.rmdir(output_dir)
# print("後片付け完了")

重要: ファイルやディレクトリをプログラムで削除する際は、対象を間違えないように細心の注意を払ってください。


まとめ:osモジュールでPythonとOSを繋げよう!

今回は、Pythonの標準ライブラリ解説シリーズ第4回として、osモジュールの基本的な使い方を学びました。

  • カレントワーキングディレクトリの取得 (os.getcwd()) と変更 (os.chdir())
  • ディレクトリの作成 (os.mkdir(), os.makedirs())、一覧取得 (os.listdir())、削除 (os.rmdir())
  • ファイルの存在確認 (os.path.exists(), os.path.isfile())、削除 (os.remove())、名前変更 (os.rename())
  • OSに依存しない安全なパス操作 (os.path.join(), os.path.split(), os.path.basename(), os.path.dirname(), os.path.abspath(), os.path.splitext())
  • 環境変数の取得 (os.environ, os.getenv())

osモジュールを使いこなすことで、あなたのPythonプログラムは単なる計算やデータ処理のツールから一歩進んで、ファイルシステムやOS環境と連携し、より広範なタスクを自動化できるようになります。例えば、大量のファイルを整理したり、バックアップを自動化したり、プログラムの実行環境に応じた設定を読み込んだりといったことが可能です。

ただし、ファイルシステムを操作する際は、誤って重要なファイルやディレクトリを削除・変更してしまわないよう、常に慎重さが求められます。テストを行う際は、影響のないテスト用のディレクトリやファイルを使うようにしましょう。

次回もPythonの便利な標準ライブラリの世界を一緒に探検していきましょう!お楽しみに!

【Python標準ライブラリ入門 第5回】表データ処理の相棒!csvモジュールでCSVファイルを自在に操ろう 📊

その他の投稿はこちら

コメント

このブログの人気の投稿

タイトルまとめ

これで迷わない!WindowsでPython環境構築する一番やさしい方法 #0

【Python標準ライブラリ完結!】11の冒険をありがとう!君のPython力が飛躍する「次の一歩」とは? 🚀