✏️

python3エンジニア認定実践試験対策②

2025/03/03に公開

はじめに

以前の記事

今回の範囲

タイトル 問題数 問題割合 備考
10 汎用OS・ランタイムサービス 2 5.0%
11 ファイルとディレクトリへのアクセス 2 5.0%

10:汎用OS・ランタイムサービス

モジュール一覧

  • osモジュール
  • ioモジュール
  • sysモジュール
  • argparseモジュール
    主観と練習問題を見た感覚だとos、sysの方が出現割合が高そうなので、os/sys -> io/argparseの順で覚えてもいいかも

osモジュール

-実行中のプロセス属性の操作、ファイルとディレクトリの操作などOSが提供する様々な機能を利用できる

実行中のプロセス属性の操作
プロセス属性 関数
環境変数 environ, getenv(), ...
ユーザーID getuid(), setuid(), geteuid(), seteuid(), ...
グループID getgid(), setuid(), getgroups(), setgroups(), ...
プロセスID getqid(), getpgid(), getppid(), ...
import os
current_env = os.environ
# 環境変数の辞書: 例 {'PATH': '/usr/bin', 'HOME': '/home/user', ...}

path_var = os.getenv('PATH')
# 'PATH'環境変数の値: 例 '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin'

user_id = os.getuid()
# 実行中のプロセスのユーザーID: 通常は 1000 などの数値(Unixのみ)

os.setuid(0)  # スーパーユーザー(root)に切り替える(実際の使用には注意が必要)
# プロセスのユーザーIDを変更

effective_user_id = os.geteuid()
# 実行中のプロセスの実効ユーザーID(Unixのみ)

os.seteuid(0)  # スーパーユーザー(root)に切り替える(実際の使用には注意が必要)
# 実効ユーザーIDを変更

group_id = os.getgid()
# 実行中のプロセスのグループID: 通常はグループ設定に依存(Unixのみ)

os.setgid(0)
# グループIDを変更する(権限が必要)

groups = os.getgroups()
# ユーザーが属するすべての補助グループのリスト(Unixのみ)

os.setgroups(groups)
# 新しいグループIDのリストを設定する(特権が必要)

current_pid = os.getpid()
# 現在のプロセスID, 例: 23456

parent_pid = os.getppid()
# 親プロセスID
ファイル操作関連の関数
関数名 解説 戻り値 pathlibモジュールにある同等の関数
chdir(path) 現在の作業ディレクトリをpathに設定する None -
chmod(path, mode, *, dir_fd=None, follow_symlinks=True) pathで指定されたファイルまたはディレクトリのモードを変更する None Path.chmod()
getcwd() 現在の作業ディレクトリを返す str Path.cwd()
listdir(path=".") pathで指定されたディレクトリ内のファイルとディレクトリを返す list Path.iterdir()
mkdir(name, mode=0o777, *, dir_fd=None) pathで指定されたディレクトリを作成する None Path.mkdir()
makedirs(name, mode=0o777, exist_ok=False) nameで指定されたディレクトリを再帰的に作成する。末端のディレクトリだけでなく、中間ディレクトリも作成する。 None Path.mkdir()
remove(path, *, dir_fd=None) pathで指定されたファイルを削除する。ディレクトリの場合はOSErrorが送出される。 None Path.unlink()
removedirs(name) nameで指定されたディレクトリをパスの末端から再帰的に削除する None -
rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None) ファイルまたはディレクトリのパスをsrcからdstに変更する None Path.rename()
rmdir(path, *, dir_fd=None) pathで指定されたディレクトリを削除する。ディレクトリが空でない場合はOSErrorを送出する None Path.rmdir()
import os
# 現在の作業ディレクトリを表示
initial_dir = os.getcwd()
# 最初のディレクトリ: 例 '/home/user/current_working_directory'

# 新しいディレクトリを作成
new_dir = 'test_directory'
os.mkdir(new_dir)
# ディレクトリ 'test_directory' を作成

# 作業ディレクトリを新しいディレクトリに変更
os.chdir(new_dir)
current_dir = os.getcwd()
# 現在のディレクトリ: 例 '/home/user/current_working_directory/test_directory'

# サブディレクトリを作成
sub_dirs = 'subdir1/subdir2/subdir3'
os.makedirs(sub_dirs)
# ディレクトリの階層 'subdir1/subdir2/subdir3' を作成

# 現在のディレクトリの内容をリスト
contents = os.listdir('.')
# 現在のディレクトリの内容: ['subdir1']

# 新しいファイルを作成
file_name = 'sample.txt'
with open(file_name, 'w') as f:
    f.write("このファイルはテスト用です。")
#ファイル 'sample.txt' を作成

# ファイルのパーミッションを変更
os.chmod(file_name, 0o444)
# ファイル 'sample.txt' のパーミッションを読み取り専用に変更

# ファイルの名前を変更
new_file_name = 'renamed_sample.txt'
os.rename(file_name, new_file_name)
# ファイル名を 'sample.txt' から 'renamed_sample.txt' に変更

# ファイルを削除
os.remove(new_file_name)
# ファイル 'renamed_sample.txt' を削除

# サブディレクトリを削除 (空の場合)
os.removedirs(sub_dirs)
# サブディレクトリ 'subdir1/subdir2/subdir3' を削除

# 作業ディレクトリを親ディレクトリに戻し、空のディレクトリを削除
os.chdir('..')
os.rmdir(new_dir)
# ディレクトリ 'test_directory' を削除

# 最後に現在のディレクトリを表示
final_dir = os.getcwd()
# 現在のディレクトリ: 例 '/home/user/current_working_directory'

sysモジュール

  • Pythonインタープリターが使用する変数や、インタープリターの動作に関連する関数を提供

sysモジュールな主な用途

ライブラリのインポートパスを操作する
  • sys.path
    インポート対象のモジュールやパッケージを探索する先となるファイルパスを格納したリスト
    sys.pathにファイルパスを追加することで、そのファイルパスに置かれたPythonパッケージやモジュールをimport文でインポートできる。
# モジュールの検索パスを取得して表示
# 現在のモジュール検索パス
current_paths = sys.path
# 例: ['/usr/bin', '/some/other/path', ...]

# 新しいパスを追加
sys.path.append('/my/custom/path')
# 新しいパスを追加後のモジュール検索パス
updated_paths = sys.path
# 例: ['/usr/bin', '/some/other/path', ..., '/my/custom/path']
プログラムを終了する
  • sys.exit()
    Pythonを終了します。
sys.exit(1)
# プログラムを終了します(終了コード1)
コンソールの入出力を扱う
  • sys.stdin
    標準入力のオブジェクト
  • sys.stdout
    標準出力のオブジェクト
  • sys.stderr
    標準エラー出力のオブジェクト
# 標準入力から1行読み込む
# input_line = sys.stdin
# 例: "Hello, World!" と入力した場合 -> 入力された内容: Hello, World!

# 標準出力に出力します (通常のprint関数はsys.stdoutを使用)
sys.stdout.write("標準出力に直接書き込みました。\n")
# 標準出力に '標準出力に直接書き込みました。' と表示

# 標準エラー出力に出力
sys.stderr.write("これはエラーメッセージです。\n")
# 標準エラーに 'これはエラーメッセージです。' と表示

sysモジュールを用いてprint()とinput()を置き換えることができる

sys.stdout.write() # print()と同じ動作。ただし、改行は入らない

sys.stdin.read() # input()と同じ動作。ただし、入力終了方法がCtrl+D

11: ファイルとディレクトリへのアクセス

Pathオブジェクト、tempfileモジュール、shutilモジュールがバランスよく出題されそう。

Pathオブジェクト

関数名 解説 戻り値
Path.cwd() 現在のディレクトリを表すパスオブジェクトを返す。クラスメソッド パスオブジェクト
Path.home() ユーザーのホームディレクトリを表すパスオブジェクトを返す。クラスメソッド パスオブジェクト
Path.chmod(mode) パスのパーミッションを変更する None
Path.exists() パスが存在する場合にTrueを返す bool
Path.glob(pattern) パスが指すディレクトリ以下のpatternに一致するファイルやディレクトリの一覧を、パスオブジェクトとして返すジェネレーターを返す ジェネレーター
Path.is_dir() パスがディレクトリである場合にTrueを返す bool
Path.is_file() パスがファイルである場合にTrueを返す bool
Path.iterdir() パス以下に存在するファイルやディレクトリの一覧を、パスオブジェクトとして返すジェネレーターを返す ジェネレーター
Path.mkdir(mode=0o777, parents=False, exist_ok=False) パスを新しいディレクトリとして返す None
Path.open(mode="r", buffering=-1, encoding=None, errors=None, newline=None) 組み込み関数open()と同様にファイルを開く ファイルオブジェクト
Path.rename(target) パスの名前を変更する。引数targetには文字列かほかのパスオブジェクトを指定する None
Path.rmdir() パスが指すディレクトリを削除する。ディレクトリは空の必要がある None
Path.touch(mode=0o666, exist_ok=True) パスにファイルが存在しなければファイルを作成する。ファイルが存在すれば更新日時を現在日時に変更する None
Path.unlink(missing_ok=False) パスのファイルを削除する None
from pathlib import Path

current_path = Path.cwd()
# 現在の作業ディレクトリ: 例 '/home/user/current_working_directory'

home_path = Path.home()
# ユーザのホームディレクトリ: 例 '/home/user'

test_dir = Path('test_directory')
test_dir.mkdir(exist_ok=True)
# 'test_directory'が作成される(既に存在する場合は何もしない)

test_file = test_dir / 'sample.txt'
test_file.touch()
# 'test_directory/sample.txt'が作成される(既に存在する場合は何もしない)

exists = test_file.exists()
# 'sample.txt'は存在するのでTrue

is_directory = test_dir.is_dir()
# 'test_directory'はディレクトリなのでTrue

is_file = test_file.is_file()
# 'sample.txt'はファイルなのでTrue

dir_contents = list(test_dir.iterdir())
# ディレクトリ内のコンテンツをリスト化: 例 [PosixPath('sample.txt')]

test_file.chmod(0o444)
# 'sample.txt'のパーミッションが読み取り専用に変更される

with test_file.open('w', encoding='utf-8') as f:
    f.write("これはテスト用のファイルです。")
# 'sample.txt'にテキストが書き込まれる

new_test_file = test_dir / 'renamed_sample.txt'
test_file.rename(new_test_file)
# 'sample.txt'が 'renamed_sample.txt' にリネームされる

new_test_file.unlink()
# 'renamed_sample.txt'が削除される

test_dir.rmdir()
# 'test_directory'が削除される(ディレクトリが空の場合)

tempfileモジュール

一時ファイルおよび一時ディレクトリを作成する機能を提供
with文と一緒に使うことで自動的に後処理を実行してくれる

tempfileモジュールが提供する呼び出し可能オブジェクト
呼び出し可能オブジェクト 解説
TemporaryFile() ファイル名のない一時ファイルをディスク上に作成する
NamedTemporaryFile() ファイル名がある一時ファイルをディスク上に作成する
SpooledTemporaryFile() 一定ファイルサイズまではデータはメモリ上で処理され、それを超えるとディスクに書き出される一時ファイルを作成する
TemporaryDirectory() 一時ディレクトリを作成する
import tempfile
import os

with tempfile.TemporaryFile() as tmpf:
    # バイナリモードで書き込み
    tmpf.write(b'Hello, World!')
    # ファイルの先頭に戻る
    tmpf.seek(0)
    # 内容を読み取る
    print(tmpf.read())  # 出力: b'Hello, World!'

with tempfile.NamedTemporaryFile(delete=True) as tmpf:
    print('Temporary file name:', tmpf.name)  # 一時ファイルの名前を表示
    tmpf.write(b'Named temporary file example.')
    tmpf.seek(0)
    print(tmpf.read())  # 出力: b'Named temporary file example.'

# 上記のブロックを抜けるとファイルは自動的に削除されます

with tempfile.SpooledTemporaryFile(max_size=100) as tmpf:
    tmpf.write(b'Spool example data that fits in memory.')
    tmpf.seek(0)
    print(tmpf.read())  # 出力: b'Spool example data that fits in memory.'
    
    # データ量が増えると自動的にディスクに書き込まれる
    tmpf.write(b'A' * 101)
    tmpf.seek(0)
    print(tmpf.read())  # データは引き続き読み取れる

with tempfile.TemporaryDirectory() as tmpdirname:
    print('Temporary directory created:', tmpdirname)
    # 一時ディレクトリ内にファイルを作成
    temp_file_path = os.path.join(tmpdirname, 'example.txt')
    with open(temp_file_path, 'w') as file:
        file.write('This is a temporary file inside a temporary directory.')
    
    # ファイルが正しく書き込まれたか確認
    with open(temp_file_path, 'r') as file:
        print(file.read())

shutilモジュール

ディレクトリ、ファイルおよびアーカイブファイルに対して高水準な操作を提供

ファイルコピー系の関数
関数名 解説 戻り値
copyfile(src, dst, *, follow_symlinks=True) ファイルsrcをファイルを指すdstにコピーする。dstにディレクトリを指定できない str
copy(src, dst, *, follow_symlinks=True) copyfile()と同様にファイルをコピーし、ファイルのパーミッションもコピーする。dstにディレクトリを指定できる str
copy2(src, dst, *, follow_symlinks=True) copy()と同等の機能に加えて、全てのメタデータを保持しようとする。dstにディレクトリを指定できる str
copymode(src, dst, *, follow_symlinks=True) パーミッションをsrcからdstにコピーする None
copystat(src, dst, *, follow_symlinks=True) パーミッション、最終アクセス時間、最終変更時間やその他のファイル情報をsrcからdstにコピーする None
import shutil
from pathlib import Path

# テスト用のファイルとディレクトリを準備
src_file = Path('src.txt')
src_file.write_text('テスト用のファイルです。')
# 'src.txt'が作成され、"テスト用のファイルです。" が書き込まれる

dst_file = Path('dst.txt')
# 'dst.txt'はまだ存在しない

src_dir = Path('src_dir')
src_dir.mkdir(exist_ok=True)
# 'src_dir'ディレクトリが作成される

dst_dir = Path('dst_dir')

shutil.copyfile(src_file, dst_file)
# 'src.txt'を 'dst.txt' に内容をコピー

shutil.copy(src_file, src_dir)
# 'src.txt'を 'src_dir'ディレクトリにコピー

shutil.copy2(src_file, src_dir / 'src_copy2.txt')
# 'src.txt'を 'src_copy2.txt'として 'src_dir'にメタデータごとコピー

shutil.copymode(src_file, dst_file)
# 'src.txt'のパーミッションモードを 'dst.txt'にコピー

shutil.copystat(src_file, dst_file)
# 'src.txt'のステータス情報(パーミッション、タイムスタンプなど)を 'dst.txt'にコピー
再帰的な操作を行う関数

ディレクトリ以下を再帰的にコピー

  • copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False, dirs_exist_ok=True)
    • src: コピー対象のディレクトリのパスを指定する。
    • dst: コピー後のディレクトリのパスを指定する。既にある場合は例外を送出する。
    • dirs_exist_ok:Trueを指定すると、コピー先のディレクトリが存在してもエラーにならない。
      shutil.ignore_pattrns()と組み合わせて特定の拡張子のファイルをコピー対象から除外するなど使い方は様々
shutil.copytree(src_dir, dst_dir)
# 'src_dir'内のすべてのファイルを 'dst_dir'としてディープコピー

ignore = shutil.ignore_pattrns(*.png, *.jpg)
shutil.copytree("./from", "./to", ignore=ignore)
関数名 解説 戻り値
rmtree(path, ignore_errors=False, onerror=None) pathで指定したディレクトリ以下のファイルをすべて削除する None
move(src, dst, copy_function=copy2) srcディレクトリ以下のファイルを再帰的にdstに移動する。コピー時に使用する関数を指定できる(デフォルトはcopy2) str
shutil.rmtree(src_dir)
# 'src_dir'とその中身全部を削除

shutil.move(str(dst_file), str(dst_dir / 'moved_dst.txt'))
# 'dst.txt'を 'dst_dir/moved_dst.txt' に移動

Discussion