logo

Python OSモジュールの総まとめ 📂プログラミング

Python OSモジュールの総まとめ

Overview 1

os is a base module that collects simple commands for operating system-dependent features. One of the reasons to use Python is that it is easy and quick to write programs, but it is very inconvenient that features that logically should be there are mixed with the shutil module. When handling the file system, you need to use both modules equally.

It’s a summary, but it’s not just scraped from the official documents, but explained focusing on the features that are actually used, so not all information is provided. If the function you are looking for is not in this post, check the official documentation.

The following table of contents is not in the order of the document but in the order of empirical utility. The more it appears on top, the more frequently it is used. Let’s look at the table of contents as a cheat sheet and find the desired function quickly.

Things that can’t be done with the os module

File copying, deletion, moving, and renaming through the command line are impossible. It is possible on the Linux terminal, but not on Windows cmd or powershell. It seems possible with os.system("foo ... ..."), but it fails with a warning, 'foo' is not an internal or external command, operable program, or batch file..

For example, if you issue a command like os.system("rm a.txt"), it means to delete a.txt, but instead, you must use a separate function with that functionality, os.remove("a.txt").

Thus, using the module-provided functions rather than accessing through the command line is not necessarily bad. Raising an error and warning when the function is used inappropriately is an important part of safe programming. The main problem is that their functions and names do not match well or are very confusing.

os Direct Methods

The most annoying part of os is that the naming is too different from Linux commands, and the next annoying thing is that these different namings lack consistency. If you only write in Python, it’s not a big problem, but it becomes quite painful if you use multiple languages.

Checking the current working path getcwd()

It means to get the current work directory. It returns the current directory as a string.

Changing the work path chdir()

It changes the work path to the directory given as a string.

File List listdir()

It means the list of a directory.

listdirs(path='.')

  • path: Provides a list of files at the path as entered as a string. If nothing is entered, it returns the file list of the current working path.

If you only want the list of files with the .txt extension in the current path, the code is as follows.2

files = os.listdir()
txt_files = [file for file in files if file.endswith(".txt")]

Command line commands system()

system(command)

  • command: Given as a string, it executes the given command in the terminal. It is conveniently used for shell scripts for task automation, monitoring, and server traversal, etc.

If you want to pause a program, you can write the code as follows.

import os
os.system("pause")

Creating new folders mkdirs(), makedirs()

mkdir(path, mode=0o777, *, dir_fd=None)

  • path: Creates a folder with the string entered as the name in the current working path. If the directory already exists, a FileExistsError occurs.

makedirs(name, mode=0o777, exist_ok=False)

  • name: Creates a folder with the name as entered as a string. Slashes / can be used to create subdirectories.
  • exist_ok: It is about whether it is okay if the path already exists. If true, it’s fine even if the path already exists, and if false (default), it raises a FileExistsError.

For example, if you want to create a sub folder under ./main from ./ without a FileExistsError, the code is as follows.

os.makedirs("main/sub", exist_ok=True)

Deletion remove(), rmdir(), removedirs()

remove()

  • It’s a function to delete files.
  • If the given path is a directory, it raises an IsADirectoryError.
  • If the file does not exist, it raises a FileNotFoundError.

rmdir()

  • It’s a function to remove a directory.
  • If the directory does not exist or is not empty, it raises a FileNotFoundError.

One might first wonder why, if there’s a function to delete directories named rmdir(), wouldn’t it make no difference if the function to delete files was named rm()? Moreover, rmdir() is difficult to use because it requires that the directory be empty. If it were a command line, you could add the -r (recursive) option to clean up subpaths at once, but this function doesn’t have that feature. To include and delete sub-trees, you must use the shutil.rmtree() of the shutil module. And the root of these weird naming problems is probably the following function.

removedirs()

  • Deletes it if there are no files in the terminal directory.
  • If successful in deleting, it moves up to the parent directory, removing it if it’s empty. That is, it recursively removes directories, but why it ‘primarily’ supports deleting upwards rather than downwards is an unknown matter. What programmers usually need is a function like shutil.rmtree().
  • It’s not to say that this function is unusable. It’s just difficult to match functions with names, hard to memorize, and the risk of unintended side effects is high from moving upwards through paths.

Renaming, moving rename(), renames(), replace()

rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)

  • It renames src to dst, and if dst already exists, it raises a FileExistsError.
  • The path of dst, except for the terminal directory, must exist. In other words, if you want to change ./a.txt to ./temp/b.txt, the ./temp folder must exist.

renames(old, new)

  • It recursively renames old to new. If you want to change ./a.txt to ./temp/b.txt and the ./temp folder doesn’t exist, it will make ./temp itself and put b.txt underneath it.

replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None)

  • It’s the same function as rename(), but the difference is that rename() may raise different errors depending on the platform, while replace() does not depend on the platform.

path

String handling join(), split()

path.join(path, *paths)

  • It joins multiple strings together to return a string that represents a directory.

path.split(path)

  • It returns the given directory string as a tuple of strings (head, tail). tail is the terminal element, and head is its parent directories.

Existence check exists(), isfile(), isdir()

path.exists(path)

  • It returns true if path exists.

path.isfile(path)

  • It returns true if path is an existing file.

path.isdir(path)

  • It returns true if path is an existing directory.

概要 1

osは、OS依存の機能に対する簡単なコマンドを集めた基本モジュールだ。Pythonを使う理由の一つは、プログラムを素早く簡単に書けることだが、shutilモジュールと混在しているため、非常に不便だ。ファイルシステムを扱う場合、二つのモジュールを均等に使用する必要がある。

一応総まとめだが、公式ドキュメントをただ引っ張ってきたわけではなく、実際に使う機能を中心に説明したので、すべての情報が含まれているわけではない。このポストで機能を見つけられなかったら、公式ドキュメントを確認しよう。

以下の目次は、ドキュメントの順番ではなく、経験的な利用度の順に作成された。上にあるほど頻繁に使われる。目次自体をチートシートと見なして、欲しい関数をすぐに探せるようにしよう。

osモジュールでできないこと

コマンドラインを通じたファイルのコピー、削除、移動、名前の変更が不可能だ。Linuxのターミナルでは可能だが、Windowsのcmdやpowershellでは不可能だ。os.system("foo ... ...")で可能だと思いきや、'foo'は内部または外部コマンド、実行可能なプログラム、またはバッチファイルではありません。という警告とともに失敗する。

例えば、os.system("rm a.txt")というコマンドを発行すると、a.txtを削除するという意味だが、代わりにその機能を持つ関数os.remove("a.txt")を別途使用しなければならない。

このように、コマンドラインへのアクセスではなく、モジュールで提供される関数を使う方法が必ずしも悪いわけではない。機能が不適切に使われたときにエラーを起こして警告することは、安全なプログラミングにおいて重要なことだ。問題の核心は、これらの機能と名前がうまくマッチしない、または非常に混乱させることだ。

os直属メソッド

osの最もイライラする部分は、ネーミングがLinuxのコマンドとあまりにも違うことで、次にイライラするのが、その違うネーミング同士の一貫性が低いことだ。Pythonだけを扱う人には大きな問題はないが、マルチ言語を使うとかなり苦痛になる。

現在の作業ディレクトリの確認getcwd()

current work directoryをgetするという意味だ。現在のディレクトリを文字列でリターンする。

作業ディレクトリの変更chdir()

文字列で指定されたディレクトリに作業ディレクトリを変更する。

ファイルリストlistdir()

directoryのlistという意味だ。

listdirs(path='.')

  • path: 文字列で入力されたパスにあるファイルのリストを提供する。何も入力されていない場合は、現在の作業ディレクトリのファイルリストをリターンする。

現在のパスで拡張子が.txtのファイルのリストのみを得たい場合、そのコードは以下の通りだ。2

files = os.listdir()
txt_files = [file for file in files if file.endswith(".txt")]

コマンドラインコマンドsystem()

system(command)

  • command: 文字列で与えられ、そのコマンドをターミナルで実行する。業務の自動化、モニタリング、サーバーの巡回などのシェルスクリプトに便利に使われる。

プログラムを一時停止したい場合は、以下のように書くことができる。

import os
os.system("pause")

新しいフォルダの作成 mkdirs(), makedirs()

mkdir(path, mode=0o777, *, dir_fd=None)

  • path: 現在の作業ディレクトリに入力された文字列を名前とするフォルダを作成する。ディレクトリが既に存在する場合は、FileExistsErrorが発生する。

makedirs(name, mode=0o777, exist_ok=False)

  • name: 入力された文字列の名前を持つフォルダを作成する。スラッシュ/を通じて下位ディレクトリも作成できる。
  • exist_ok: 既にそのパスが存在しても良いかについてのものだ。真ならば、パスが既に存在しても問題ないし、偽(デフォルト)ならばFileExistsErrorを発生させる。

例えば、./から./mainの下位フォルダであるsubフォルダをFileExistsErrorなしで一度に作成したい場合、そのコードは以下の通りだ。

os.makedirs("main/sub", exist_ok=True)

削除 remove(), rmdir(), removedirs()

remove()

  • ファイルを削除するための関数だ。
  • 指定されたパスがディレクトリならばIsADirectoryErrorを発生させる。
  • ファイルが存在しない場合はFileNotFoundErrorを発生させる。

rmdir()

  • ディレクトリを削除するための関数だ。
  • ディレクトリが存在しないか空ではない場合はFileNotFoundErrorを発生させる。

ディレクトリを削除する関数の名前がrmdir()なら、ファイルを削除する関数はrm()でも良いのでは?と思うのが最初に来る。しかもrmdir()はディレクトリが空でなければならないという点で使いにくい。コマンドラインなら-r(再帰)オプションを入れて下位パスも一度に片付けることができるが、この関数にはその機能もない。下位ツリーを含めて削除するにはshutilモジュールのshutil.rmtree()を使用しなければならない。そして、このような奇妙な名前問題の根源はおそらく次の関数だろう。

removedirs()

  • 末端ディレクトリ内にファイルがなければ削除する。
  • 削除に成功すれば、逆に上位ディレクトリをたどりながら空なら削除する。つまり、再帰的にディレクトリを削除するが、なぜ下位ではなく上位に削除する関数を「優先的に」サポートするのかは分からないことだ。通常の状況では、プログラマーに必要なのはshutil.rmtree()のような機能だからだ。
  • この関数が便利に使えないというわけではない。機能と名前をマッチさせるのが難しく、覚えるのが難しいし、パスを逆にたどるという点で意図しない副作用につながるリスクが大きいだけだ。

名前の変更、移動 rename(), renames(), replace()

rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)

  • srcの名前をdstに変更するが、dstが既に存在する場合はFileExistsErrorを発生させる。
  • dstのパスは、末端ディレクトリを除いて存在する必要がある。つまり、./a.txt./temp/b.txtに変更したい場合./tempフォルダが存在する必要がある。

renames(old, new)

  • oldの名前をnewに再帰的に変更する。./a.txt./temp/b.txtに変更したいとき、./tempフォルダが存在しない場合は、./tempを自ら作成して、b.txtをその下に入れる。

replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None)

  • rename()と同じ関数だが、rename()はプラットフォームによ