Pythonに少し慣れてくると、ファイルやフォルダを扱いたくなる場面が増えてきます。たとえば、集計結果を日付ごとのフォルダに保存したいときなどです。
そんなとき、検索するとかならず出てくるのが import os という1行ですよね。でも、osでいったい何ができるのか、全体像をつかめないまま使っている方も多いのではないでしょうか。
osモジュールは、Pythonからパソコンの基本的な機能を呼び出すための標準ライブラリです。フォルダの作成やファイルの一覧、パスの組み立てなど、日常的に使う操作がひととおりそろっています。
今回は、osモジュールのよく使う機能を、手元のPython 3.11で動かした結果とともに紹介します。ファイル操作が初めての方でも読み進められるように、ひとつずつ説明していきますね。
osモジュールとは何か¶
最初に、osという名前の意味から整理しておきましょう。osは、Operating Systemの略です。WindowsやmacOS、Linuxといった、パソコンを動かす土台のソフトウェアのことですね。
osモジュールは、こうしたOSの機能をPythonから使うための窓口です。標準ライブラリなので、pipでのインストールは必要ありません。
大事なのは、OSごとの違いをある程度吸収してくれる点です。同じコードがWindowsでもmacOSでも動くように、できるだけ共通の書き方で操作できるよう作られています。
いま動いている環境がどのOSなのかは、os.nameで確認できます。手元のLinuxで表示すると posix と出ました。Windowsでは nt になります。
import os
print(os.name) # posix(Windowsでは nt)
print(os.sep) # /(Windowsでは \)
os.sepは、パスの区切り文字です。Windowsとそれ以外で区切り文字が違うことが、あとで紹介するos.path.joinを使う理由につながっていきます。
osモジュールでできることの全体像¶
osにはたくさんの関数がありますが、初心者がまず覚えるべきものはそれほど多くありません。よく使うものを、目的別に表で整理してみました。
| 目的 | 関数 | ひとことで言うと |
|---|---|---|
| 現在地を知る | os.getcwd() | いまいるフォルダのパスを返す |
| 現在地を移動 | os.chdir() | 作業するフォルダを変える |
| フォルダを作る | os.makedirs() | 途中のフォルダもまとめて作る |
| 一覧を取る | os.listdir() | フォルダの中身の名前を返す |
| 中まで全部たどる | os.walk() | サブフォルダも含めて順に見る |
| ファイルを消す | os.remove() | ファイルを1つ削除する |
| 名前を変える | os.rename() / os.replace() | ファイルやフォルダの名前を変える |
| パスを扱う | os.path.join() など | パスの組み立てや分解 |
このほかに、環境変数を読むos.environもよく使われます。環境変数については別の記事で詳しく書いているので、ここでは触れる程度にしておきます。【関連記事】環境変数とは?PythonでAPIキーを安全に扱う.envと os.environ の基本を初心者向けに解説
現在地を知る getcwd と chdir¶
ファイル操作でいちばん最初につまずくのが、現在地の考え方です。プログラムの中で data.csv とだけ書いたとき、Pythonはどこを探しにいくのでしょうか。
答えは、カレントディレクトリと呼ばれる、いま作業しているフォルダです。これはos.getcwd()で確認できます。
import os
print(os.getcwd()) # 例: /home/user/project
ここで注意したいのは、カレントディレクトリはスクリプトが置いてある場所とは限らないことです。どこから実行したかによって決まります。
たとえばターミナルでホームフォルダにいたまま python project/main.py と実行すると、カレントディレクトリはホームフォルダのままです。すると、main.pyと同じ場所にあるdata.csvが見つからず、FileNotFoundErrorになってしまいます。
os.chdir()を使えば、作業するフォルダを途中で変えることもできます。ただ、プログラム全体に影響が出るので、むやみに使わないほうが安全です。
パスを安全に組み立てる os.path¶
ファイルの場所を表す文字列を、パスと呼びます。パスを文字列の足し算で作ると、区切り文字の違いでWindowsだけ動かない、といったことが起こりがちです。
そこで使うのが、os.pathというサブモジュールです。中でもos.path.join()は、OSに合った区切り文字でパスをつないでくれます。
よく使うos.pathの関数¶
まずは、手元で試した結果を見てください。
import os
print(os.path.join("data", "2026", "report.csv"))
# data/2026/report.csv(Windowsでは data\2026\report.csv)
path = "/home/user/app/main.py"
print(os.path.basename(path)) # main.py
print(os.path.dirname(path)) # /home/user/app
print(os.path.splitext("report.final.csv")) # ('report.final', '.csv')
basenameはファイル名だけ、dirnameはフォルダ部分だけを取り出します。splitextは拡張子を切り分ける関数で、ドットが複数あっても最後のドットで分けてくれました。
存在を確かめる関数もよく使います。os.path.exists()はあるかどうか、isfile()はファイルかどうか、isdir()はフォルダかどうかを、TrueかFalseで返します。
joinの意外な落とし穴¶
便利なos.path.joinにも、知っておきたい性質があります。途中に絶対パスがまざると、それより前の部分が捨てられてしまうのです。
実際に試してみると、次のようになりました。
print(os.path.join("data", "/tmp", "a.txt")) # /tmp/a.txt
dataフォルダの中に保存するつもりが、まったく別の場所を指してしまっています。公式ドキュメントにも、絶対パスの部分があればそれ以前の部分は無視されると書かれています。
ユーザーの入力をjoinに渡すときは、先頭にスラッシュが付いていないかを確かめておくと安心です。
フォルダを作る makedirs と exist_ok¶
次は、フォルダの作成です。osにはmkdir()とmakedirs()の2つがありますが、迷ったらmakedirsを選べば大丈夫です。
mkdirは1階層だけを作る関数で、途中のフォルダが無いとエラーになります。makedirsは、output/logs のように途中のフォルダもまとめて作ってくれます。
ここで覚えておきたいのが、exist_okという引数です。
import os
os.makedirs("output/logs", exist_ok=True)
exist_okを付けないと、すでにフォルダがあるときにFileExistsErrorになります。手元でも、2回目の実行でこのエラーが出ました。
exist_ok=Trueにしておけば、フォルダがあってもなくてもエラーにならないので、毎回同じコードを安心して実行できます。この引数はPython 3.2で追加されたもので、いまではほとんどの場面で付けておくのが定番です。
フォルダの中身を見る listdir・walk・scandir¶
フォルダの中にあるファイルを調べる方法は、3種類あります。それぞれ得意なことが違うので、順番に見ていきましょう。
listdirは名前だけを返す¶
いちばんシンプルなのがos.listdir()です。指定したフォルダの中にある、ファイルやフォルダの名前をリストで返します。
ここでひとつ注意があります。公式ドキュメントには、返ってくるリストの順番は決まっていないと明記されているのです。
手元では、たまたま名前順に見えることもありました。しかし、環境が変わると順番も変わる可能性があります。順番が大事な処理では、sorted()で並べ替えてから使いましょう。
print(sorted(os.listdir("output"))) # ['a.txt', 'logs']
walkはサブフォルダまでたどる¶
フォルダの中のフォルダまで、すべて調べたいこともありますよね。そんなときはos.walk()が便利です。
walkは、フォルダごとに3つの値の組を順番に返してくれます。いまのフォルダのパス、その中のフォルダ名の一覧、ファイル名の一覧です。
import os
for root, dirs, files in os.walk("output"):
for name in files:
print(os.path.join(root, name))
# output/a.txt
# output/logs/b.log
rootとファイル名をjoinでつなげば、すべてのファイルのパスが手に入ります。ログの整理や、特定の拡張子のファイル探しなど、実務でもよく使う書き方です。
scandirは種類も一緒にわかる¶
3つ目のos.scandir()は、名前と一緒に、ファイルなのかフォルダなのかといった情報も返してくれます。公式ドキュメントでは、種類や属性の情報も必要な場合、listdirより大幅に速くなりうると説明されています。
with os.scandir("output") as entries:
for entry in entries:
print(entry.name, entry.is_dir())
3つの使い分けを、表にまとめておきます。
| 関数 | 返すもの | 向いている場面 |
|---|---|---|
| os.listdir() | 名前のリスト | 中身をざっと確認したい |
| os.walk() | フォルダごとの組 | サブフォルダまで全部たどりたい |
| os.scandir() | 種類などの情報付きの項目 | ファイル数が多く速さも欲しい |
ファイルの削除と名前の変更¶
ファイルを消すときは、os.remove()を使います。ただし、消せるのはファイルだけで、フォルダを渡すとエラーになりました。
空のフォルダならos.rmdir()で消せますが、中身があるとOSErrorになります。中身ごとフォルダを消したいときは、shutilのrmtree()を使うのが一般的です。【関連記事】Pythonのshutilとは?ファイルのコピーや移動、zip圧縮を自動化する基本を初心者向けに解説
osで消したファイルは、ゴミ箱を経由せずにすぐ削除されます。元に戻せないので、最初はprintで対象を表示して確認してから消すようにしましょう。
名前の変更には、os.rename()とos.replace()があります。違いが出るのは、変更先の名前のファイルがすでにあるときです。
replaceは、変更先が既存のファイルなら黙って上書きします。renameは、Windowsではこの場合にエラーになるため、OSによって動きが変わってしまいます。どの環境でも同じ動きにしたいなら、replaceを選んでおくのが無難です。
pathlibとの使い分け¶
ここまで読んで、pathlibでも同じことができるのでは、と思った方もいるかもしれません。その通りで、Python 3.4から加わったpathlibは、パスをオブジェクトとして扱える新しい方法です。
両者の書き方を、表で比べてみました。
| やりたいこと | os | pathlib |
|---|---|---|
| パスをつなぐ | os.path.join("data", "a.csv") | Path("data") / "a.csv" |
| 存在を確認 | os.path.exists(p) | p.exists() |
| フォルダ作成 | os.makedirs(p, exist_ok=True) | p.mkdir(parents=True, exist_ok=True) |
| 一覧を取る | os.listdir(p) | p.iterdir() |
新しく書くコードなら、読みやすさの面でpathlibをおすすめします。一方で、古いコードやネット上のサンプルの多くはosで書かれているので、両方読めるようにしておくと困りません。【関連記事】Pythonのpathlibとは?ファイルパス操作を初心者向けに解説
また、環境変数やプロセスの情報、CPUの数を調べるos.cpu_count()のように、pathlibには無い機能もosにはあります。どちらか片方だけ覚えるのではなく、得意分野で使い分けるのが現実的です。
現場で学んだ、osまわりの失敗¶
私は10年ほどエンジニアとして開発に関わってきましたが、ファイル操作のトラブルはいまでも油断できません。中でも記憶に残っているのは、毎晩動く集計スクリプトがある日から結果を出さなくなった件です。
原因は、cronから実行したときのカレントディレクトリが、手元で試したときと違っていたことでした。相対パスで書いたフォルダが見つからず、エラーログだけが静かに積み上がっていたのです。
それ以来、ファイルの場所はスクリプト自身の位置を基準に組み立てるようにしています。os.path.dirname(os.path.abspath(__file__)) でスクリプトのあるフォルダを取り、そこからjoinでたどる形です。
もうひとつの失敗は、listdirの順番に頼っていたことでした。開発用のパソコンでは名前順に並んでいたのに、本番サーバーでは順番が変わり、処理の結果がずれてしまったのです。
どちらも、ドキュメントを最初にきちんと読んでいれば防げたミスでした。皆さんも、動いたから大丈夫と思わず、環境が変わったらどうなるかを一度考えてみてください。
まとめ¶
osモジュールは、PythonからOSの基本的な機能を使うための標準ライブラリです。インストール不要で、フォルダの作成やファイルの一覧、パスの操作など、ファイルまわりの基本がそろっています。
押さえておきたいのは、カレントディレクトリは実行した場所で決まることです。パスはos.path.joinで組み立て、フォルダはmakedirsにexist_ok=Trueを付けて作りましょう。
中身を調べるときは、目的に合わせてlistdir、walk、scandirを選びます。listdirの順番は決まっていないので、並びが大事ならsortedで並べ替えてください。
ファイルを開いて読み書きする方法とあわせて覚えると、できることが一気に広がります。【関連記事】Pythonのファイル読み書きとは?open()とwith文の基本を初心者向けに解説
まずは、自分のパソコンでos.getcwd()を表示してみるところから始めてみてください。いま自分がどこにいるのかを知ることが、ファイル操作で迷わないための第一歩です。
ここまでお読みいただきありがとうございました。