OS・ランタイムとファイルの操作の要点
内容の確認日: 2026-10-04
この分野は『Python実践レシピ』の第 10 章 (汎用 OS・ランタイムサービス・2 問) と第 11 章 (ファイルとディレクトリへのアクセス・2 問) に対応します。コマンドラインのツールを作るときに使うモジュールが中心です。
特に argparse の引数の指定方法と、pathlib のパスの各部分を取り出す属性 (name・stem・suffix・parent) は、結果を問う問題が作りやすいので、細かく覚えておきましょう。
os・io・sys
os.environ は環境変数を辞書のように扱うオブジェクトです。設定されていないかもしれない変数は、os.environ.get(名前, 既定値) で読みます (os.environ[名前] は KeyError)。os.path にはパスの文字列を扱う関数 (join・basename・dirname・splitext・exists など) があります。
io.StringIO はメモリ上の文字列を、io.BytesIO はバイト列を、ファイルのように読み書きできるオブジェクトです。ファイルを受け取る関数のテストや、文字列を組み立てるのに使います。getvalue() で全体を取り出し、tell()・seek() で読み書きの位置を扱います。
sys.argv はコマンドライン引数のリストで、先頭はスクリプト名です。sys.exit(終了コード) は SystemExit 例外を送出してプログラムを終了します。ほかに、sys.path (モジュールを探すパス)・sys.version_info (バージョン)・sys.stdin・sys.stdout・sys.stderr があります。
import ioimport osimport sysprint(os.environ.get("APP_MODE", "development"))print(os.path.splitext("archive.tar.gz"), os.path.basename("/var/log/app.log"))buf = io.StringIO()print("header", file=buf)buf.write("body")print(repr(buf.getvalue()))print(sys.argv[1:], sys.version_info >= (3, 10))sys.exit(0)print("ここは実行されない")python3 main.py data.csv -v development ('archive.tar', '.gz') app.log 'header\nbody' ['data.csv', '-v'] True
コマンドライン引数 (argparse)
argparse.ArgumentParser に add_argument で引数を定義し、parse_args() で解析すると、結果が Namespace オブジェクトの属性として得られます。-h・--help の使い方の表示も自動で作られます。
・- で始まらない名前は位置引数 (必須)。-n・--count のような名前はオプション引数で、属性名は長い名前から決まる
・type=int: 値を変換する。default: 省略時の値。required=True: オプション引数を必須にする
・choices=[...]: 指定できる値を限定する
・nargs: 値の個数。"?" は 0 か 1 個 (値なしのときは const)、"*" は 0 個以上、"+" は 1 個以上 (リストになる)
・action="store_true": 値を取らないフラグ。"append": 指定のたびにリストに追加。"count": 指定の回数を数える
import argparseparser = argparse.ArgumentParser(description="ファイルを集計する")parser.add_argument("files", nargs="+")parser.add_argument("-n", "--top", type=int, default=10)parser.add_argument("--format", choices=["csv", "json"], default="csv")parser.add_argument("-v", "--verbose", action="count", default=0)parser.add_argument("--dry-run", action="store_true")args = parser.parse_args(["a.log", "b.log", "-n", "3", "-vv", "--dry-run"])print(args.files, args.top, args.format, args.verbose, args.dry_run)python3 main.py ['a.log', 'b.log'] 3 csv 2 True
--dry-run のようにハイフンを含む名前は、属性名ではアンダースコア (dry_run) になります。解析でエラーがあると、使い方を表示して終了コード 2 で終了します。
パスの操作 (pathlib)
pathlib.Path はパスをオブジェクトとして扱うクラスで、os.path の関数よりも直観的に書けます。/ 演算子でパスをつなげ、属性でパスの各部分を取り出せます。
・name: ファイル名。stem: 最後の拡張子を除いた名前。suffix: 最後の拡張子。suffixes: すべての拡張子
・parent: 親ディレクトリ。parts: 各部分のタプル
・with_name・with_suffix・with_stem: 一部を置き換えたパス
・relative_to: 相対パス。is_relative_to: その下にあるか
・つなぐ側が絶対パスなら、それより前は捨てられる (Path("/srv") / "/etc" は /etc)
from pathlib import PurePosixPathp = PurePosixPath("/srv/app") / "static" / "report.tar.gz"print(p)print(p.name, p.stem, p.suffix, p.suffixes)print(p.parent, p.with_suffix(".zip"), p.relative_to("/srv"))print(PurePosixPath("/srv/app") / "/etc/hosts")python3 main.py /srv/app/static/report.tar.gz report.tar.gz report.tar .gz ['.tar', '.gz'] /srv/app/static /srv/app/static/report.tar.zip app/static/report.tar.gz /etc/hosts
PurePosixPath はファイルシステムにアクセスしない、パスの文字列操作だけのクラスです。Path はさらに、ファイルシステムを操作するメソッドを持ちます。
・存在の確認: exists()・is_file()・is_dir()
・作成: mkdir(parents=True, exist_ok=True) (途中のディレクトリも作り、あってもエラーにしない)
・読み書き: read_text・write_text・read_bytes・write_bytes・open()
・一覧: iterdir() (直下)・glob("*.py") (直下でパターンに一致)・rglob("*.py") (サブディレクトリまで再帰的に)
・削除・移動: unlink() (ファイル)・rmdir() (空のディレクトリ)・rename()
一時ファイルと高レベルなファイル操作 (tempfile・shutil)
tempfile.TemporaryDirectory() を with 文で使うと、一時ディレクトリが作られ、ブロックを抜けると中身ごと自動で削除されます。TemporaryFile・NamedTemporaryFile は一時ファイルで、閉じると削除されます (NamedTemporaryFile は name 属性でパスを得られます)。
shutil は、ファイルやディレクトリをまとめて操作する関数を持つモジュールです。copy (内容と権限)・copy2 (更新日時などのメタデータも)・copytree (ディレクトリごと)・move (移動)・rmtree (中身ごと削除。ごみ箱には移らない)・which (コマンドのパスを探す) などがあります。
import shutilimport tempfilefrom pathlib import Pathwith tempfile.TemporaryDirectory() as tmp: src = Path(tmp) / "src" (src / "pkg").mkdir(parents=True) (src / "main.py").write_text("print('hi')", encoding="utf-8") (src / "pkg" / "util.py").write_text("", encoding="utf-8") (src / "README.md").write_text("# demo", encoding="utf-8") print(sorted(p.name for p in src.glob("*.py"))) print(sorted(p.name for p in src.rglob("*.py"))) shutil.copytree(src, Path(tmp) / "backup") shutil.rmtree(src) print(src.exists(), sorted(p.name for p in (Path(tmp) / "backup").iterdir()))print(Path(tmp).exists())python3 main.py ['main.py'] ['main.py', 'util.py'] False ['README.md', 'main.py', 'pkg'] False
試験でよくある引っかけ
os.environ[名前]のKeyError設定されていない環境変数は
os.environ.get(名前, 既定値)で読みます。sys.argv[0]はスクリプト名引数だけが欲しいときは
sys.argv[1:]を使います。sys.exit()は例外sys.exit()はSystemExitを送出するので、その後のコードは実行されません (except SystemExitで捕捉はできます)。store_trueのオプション値を取らず、指定すると
True、省略するとFalseです。suffixとsuffixesreport.tar.gzのsuffixは最後の.gzだけ、stemはreport.tarです。絶対パスをつなぐ
Path("/srv") / "/etc"は/etcになり、前のパスは捨てられます。globとrglobglob("*.py")は直下だけ、rglob("*.py")はサブディレクトリまで探します。空でないディレクトリの削除
rmdir()は空のディレクトリだけです。中身ごと消すのはshutil.rmtree()です。
問題で確認する
この分野の問題を、解説つきで読めます (登録不要)。
出典・参考
- Python エンジニア育成推進協会「Python 実践試験」(出題範囲)
- Python ドキュメント「os」
- Python ドキュメント「sys」
- Python ドキュメント「argparse」
- Python ドキュメント「pathlib」
- Python ドキュメント「shutil」
コード例は、実際に実行して結果を確認しています。