【基本】システム開発時に役立ちそうなPythonのファイル操作色々

2022-08-31

Pocket

こんにちは、爽です。皆さん、いかがお過ごしでしょうか?

今回はシステム開発時に役立ちそうなPythonのファイル操作について色々確認します。
ファイル操作の基本は以下の記事で紹介しましたが、今回は以下の記事の内容を前提にシステム開発時に使えそうなファイル操作のTips的なものをまとめていきたいと思います。

■この記事の対象読者
・Pythonのファイル操作の基本を理解している方
・Pythonのファイル操作する際の開発情報を収集している方

なお、私はPythonをAnacondaをインストールしてJupyterで実行しています。MacのAnacondaのインストール方法とJupyterの使い方は下記記事にまとめているので良かったらご参考ください。

それではどうぞ!

ファイル操作(glob,os,pathlib,shutil)

ここではファイル操作のための代表的なライブラリとメソッドを使い方とともにまとめます。
ファイル操作は以下で紹介しているglob,os,pathlib,shutilあたりのライブラリを押さえておき、他にやりたいことがあれば検索して頂けるとファイルの操作系は十分かと思います。

Noライブラリメソッド概要
1osgetcwd()現在Pythonを実行中のディレクトリを取得する
2listdir(ディレクトリ名)ディレクトリ配下のディレクトリ及びファイルの一覧をリスト型で取得する
3path.exists(ファイル名、もしくはディレクトリ)ファイル、もしくはディレクトリが存在するかどうかを判定し、結果をBoolean型で返す
4path.isfile(ファイル名)ファイルが存在するかどうかを判定し、結果をBoolean型で返す
5path.isdir(ディレクトリ名)ファイルがない場合は新規作成、同名のファイルがある場合は追記を行う
6rename(変更元ファイル,変更先ファイル)ファイル名を変更する
7symlink(同期したいファイル,同期したいファイル)片方のファイルが変更されるともう一方も同じ変更がファイルに反映される
8remove(ファイル名)ファイルを削除する
9mkdir(ディレクトリ名)ディレクトリを作成する
10rmdir(ディレクトリ名)ディレクトリを削除する(ただし空ディレクトリのみを削除可能)
11pathlibPath(ファイル名).touch()空ファイルを作成する
12globglob(ディレクトリ名/*)ディレクトリ配下のディレクトリとファイル一覧をリストで取得する
13shutilcopy(コピー元ファイル名,コピー先ファイル名)ファイルをコピーする
14rmtree(ディレクトリ名)ディレクトリごと配下のディレクトリとファイル全てを削除する
import glob
import os
import pathlib
import shutil

#No.1:getcwd()で現在のディレクトリを取得
os.getcwd()
# '/Users/ユーザー名/Python_Programing'

#No.2:listdir()で配下のディレクトリ及びファイルをリストで取得
print(os.listdir('/Users/ユーザー名/Python_Programing'))
# ['test1.ipynb', 'test2.txt', 'test.csv', 'test2.py', 'dir', '.ipynb_checkpoints']

#No.3:path.exists()でファイルもしくはディレクトリが存在するかを判定
print(os.path.exists('dir'))
print(os.path.exists('test2.txt'))
# True
# True

#No.4:path.isfile()でファイルかどうかを判定
print(os.path.isfile('dir'))
print(os.path.isfile('test2.txt'))
# False
# True

#No.5:path.isdir()でファイルかどうかを判定
print(os.path.isdir('dir'))
print(os.path.isdir('test2.txt'))
# True
# False

#No.6:rename()でファイル名を変更
os.rename('test.csv', 'test100.csv')
print(os.listdir('/Users/ユーザー名/Python_Programing'))
# ['test100.csv', 'test1.ipynb', 'test2.txt', 'test2.py', 'dir', '.ipynb_checkpoints']

#No.7:symlink()でファイルを同期
#ファイルの内容を取得
with open('test2.txt', 'r') as f:
    print(f.read())
# 123
# ABC
# あいう
# アイウ

os.symlink('test2.txt', 'symlink.txt')

#元ファイルを変更
with open('test2.txt', 'a') as f:
    f.write('AAA')

#同期先のファイルも更新されていることを確認
with open('test2.txt', 'r') as f:
    print(f.read())
with open('symlink.txt', 'r') as f:
    print(f.read())
# 123
# ABC
# あいう
# アイウ
# AAA

# 123
# ABC
# あいう
# アイウ
# AAA

#No.8:remove()でファイルを削除
os.remove('symlink.txt')
print(os.listdir('/Users/ユーザー名/Python_Programing'))
# ['test100.csv', 'test1.ipynb', 'test2.txt', 'test2.py', 'dir', '.ipynb_checkpoints']

#No.9:mkdir()でディレクトリを作成
os.mkdir('mkdir')
print(os.listdir('/Users/ユーザー名/Python_Programing'))
# ['test100.csv', 'test1.ipynb', 'test2.txt', 'symlink.txt', 'test2.py', 'dir', 'mkdir', '.ipynb_checkpoints']

#No.10:rmdir()でディレクトリを削除
os.rmdir('mkdir')
print(os.listdir('/Users/ユーザー名/Python_Programing'))
# ['test100.csv', 'test1.ipynb', 'test2.txt', 'symlink.txt', 'test2.py', 'dir', '.ipynb_checkpoints']

#No.11:Path('empty.txt').touch()で空ファイルを作成
pathlib.Path('empty.txt').touch()
print(os.listdir('/Users/ユーザー名/Python_Programing'))
# ['empty.txt', 'test100.csv', 'test1.ipynb', 'test2.txt', 'test2.py', 'dir', '.ipynb_checkpoints']

#No.13:glob()で配下のディレクトリのファイル一覧をリストで取得
pathlib.Path('dir/empty1.txt').touch()
pathlib.Path('dir/empty2.txt').touch()
glob.glob('dir/*')
# ['dir/empty2.txt', 'dir/empty1.txt']

#No.14:copy()でファイルをコピー
shutil.copy('dir/empty2.txt', 'dir/empty2_copy.txt')
glob.glob('dir/*')
# ['dir/empty2_copy.txt', 'dir/empty2.txt', 'dir/empty1.txt']

#No.15:rmtree()でディレクトリごと配下のディレクトリとファイル全てを削除
print(os.listdir('/Users/ユーザー名/Python_Programing'))
# ['empty.txt', 'test100.csv', 'test1.ipynb', 'test2.txt', 'test2.py', 'dir', '.ipynb_checkpoints']
shutil.rmtree('dir')
print(os.listdir('/Users/ユーザー名/Python_Programing'))
# ['empty.txt', 'test100.csv', 'test1.ipynb', 'test2.txt', 'test2.py', '.ipynb_checkpoints']

ファイルの圧縮と展開(tarfile,zipfile

こちらではtarファイル及びzipファイルの圧縮と展開のためライブラリとメソッドを使い方とともにまとめます。

tarfile

tarファイルはUnixやLinux,Macなどで扱われる拡張子が.tar.gzで終わる圧縮ファイルです。Windowsで言うと.zipです。tarファイルを扱うためのライブラリはtarfileです。

圧縮はopen()メソッドの第一引数に圧縮先のtarファイルのパスを指定し、第二引数にモードとして’w:gz’を指定します。そして、openの中でadd()メソッドを使って、tarファイルとして圧縮したいディレクトリを指定します。

import tarfile

#圧縮
with tarfile.open('圧縮先のパス', 'w:gz') as tr:
    tr.add('圧縮元のパス')

展開も同様にopen()メソッドの第一引数に展開したいtarファイルのパスを指定し、第二引数にモードとして’r:gz’を指定します。そして、openの中でextractall()メソッドを使って、pathにtarファイルの展開先パスを指定します。
なお、展開せずにtarファイルの中の一部のファイルを読み込みたい場合は、extractfile()メソッドを使用します。

import tarfile

#展開
with tarfile.open('展開元のパス', 'r:gz') as tr:
    tr.extractall(path='展開先のパス')

#tarを展開せずに一部のファイルを読み込み
with tarfile.open('展開元のパス', 'r:gz') as tr:
    with tr.extractfile('読み込みたいファイルのパス') as f:
        print(f.read())

下記にtarファイルの圧縮と展開のためのサンプルコードを記載します。

import glob
import os
import tarfile

#dirの中身確認
print(glob.glob('dir/*'))
print(glob.glob('dir/sub_dir/*'))
# ['dir/sub_dir', 'dir/test.txt']
# ['dir/sub_dir/sub_test.txt']

#dirをtarファイルとして圧縮
#第一引数に圧縮先のパスを指定する
with tarfile.open('test.tar.gz', 'w:gz') as tr:
    tr.add('dir')
print(os.path.isfile('test.tar.gz'))
# True

#tarファイルとして圧縮したファイルを展開
#第一引数に展開元のパスを指定する
with tarfile.open('test.tar.gz', 'r:gz') as tr:
    #pathに展開先のパスを指定する
    tr.extractall(path='tar_dir')
print(os.path.isdir('tar_dir'))
# True

#tarファイルを展開せずに一部のファイルを読み込み
with tarfile.open('test.tar.gz', 'r:gz') as tr:
    with tr.extractfile('dir/sub_dir/sub_test.txt') as f:
        print(f.read())
        # b'sub_test'

zipfile

zipファイルを扱うためのライブラリはzipfileです。

圧縮はZipFile()メソッドの第一引数に圧縮先のzipファイルのパスを指定し、第二引数にモードとして’w’を指定します。そして、openの中でwrite()メソッドを使って、zipファイルとして圧縮したいディレクトリを指定します。
なお、この方法だと圧縮先のディレクトリに追加したいファイルを一つずつ指定する必要があるので少し手間です。

import zipfile

#圧縮の基本系。ただしこの方法だとwrite()メソッドの中で一つずつファイルを指定する必要があるので手間
with zipfile.ZipFile('圧縮先のパス', 'w') as z:
    z.write('圧縮元のパス')
    z.write('圧縮元のファイル')

そんな手間を解消する為には、globとループを組み合わせることで解決できます。

import glob
import zipfile

#この方法だと一発で圧縮元のディレクトリとファイルを圧縮できる
with zipfile.ZipFile('圧縮先のパス', 'w') as z:
    for f in glob.glob('圧縮元のパス/**', recursive=True)
    z.write(f)

展開はtarの時と似ていて、ZipFile()メソッドの第一引数に展開したいzipファイルのパスを指定し、第二引数にモードとして’r’を指定します。そして、ZipFile()メソッドの中でextractall()メソッドを使って、zipファイルの展開先パスを指定します。
なお、展開せずにzipファイルの中の一部のファイルを読み込みたい場合は、ZipFile()メソッドの中でopen()メソッドとread()メソッドを使用します。

import zipfile

#展開
with zipfile.ZipFile('展開元のパス', 'r') as z:
    z.extractall('展開先のパス')

#zipを展開せずに一部のファイルを読み込み
with zipfile.ZipFile('展開元のパス', 'r') as z:
    with z.open('読み込みたいファイルのパス') as f:
        print(f.read())

下記にzipファイルの圧縮と展開のためのサンプルコードを記載します。

import glob
import os
import zipfile

#dirの中身確認
print(glob.glob('dir/*'))
print(glob.glob('dir/sub_dir/*'))
# ['dir/sub_dir', 'dir/test.txt']
# ['dir/sub_dir/sub_test.txt']

#dirをzipファイルとして圧縮
#第一引数に圧縮先のパスを指定する
with zipfile.ZipFile('test.zip', 'w') as z:
    #圧縮元のパスを指定
    for f in glob.glob('dir/**', recursive=True):
        z.write(f)
print(os.path.isfile('test.zip'))
# True

#zipファイルとして圧縮したファイルを展開
#第一引数に展開元のパスを指定する
with zipfile.ZipFile('test.zip', 'r') as z:
    #パスを指定する
    z.extractall('zip_dir')
print(os.path.isdir('zip_dir'))
# True

#zipファイルを展開せずに一部のファイルを読み込み
with zipfile.ZipFile('test.zip', 'r') as z:
    with z.open('dir/sub_dir/sub_test.txt') as f:
        print(f.read())
        # b'sub_test'

Template()メソッド

Template()メソッドは引数で指定したファイルを読み込み専用のものとして扱えるメソッドです。
実際にテンプレートファイルとして読み込ませるファイルを用意した後、下記のサンプルコードのようにテンプレートとなるファイルを読み込み、substitute()メソッドを使って、テンプレートに値を代入することができます。

Hi $name.

$contents

Have a good day!
import string

#テンプレートとなるファイルを読み込み
with open('design/template.txt') as f:
    #Template()メソッドで読み込み専用のものとして変数に入れる
    t = string.Template(f.read())
#substitute()メソッドを使ってテキストファイルの中身に値を代入できる
contents = t.substitute(name='Sou', contents='How are you?')
print(contents)


これはプログラマとデザイナーが分業している場合に使えると思います。
テンプレートファイルに記載した内容をプログラムの中で使っていると、プログラマが開発中に何かの拍子に変数が書き換えてしまう可能性があります。また、デザイナーはプログラムを読むのが得意ではないと想定される為、やはりテンプレートの内容はプログラムの中に書くべきではありません。
従って、このような時はTemplate()メソッドを使用するのが良いと思います。

参考資料

この記事はUdemyの現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用 +アメリカのシリコンバレー流コードスタイルという講座を参考にさせていただき、作成しました。

現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用 +アメリカのシリコンバレー流コードスタイル

画像に alt 属性が指定されていません。ファイル名: a1ee3d048d6aa860662b6f58c4aa167f-1024x328.png
Udemyより抜粋

当講座はPythonの基礎から応用まで幅広く学べる講座なのでおすすめです。
この講座の講師はとにかくPythonについての知識が豊富ですし、話も適度な速さで聞き取りやすいです。さすがのシリコンバレーです。
また、最後の方に機械学習で使うライブラリについても解説があるので、データサイエンス・AIについても多少知ることができます。

当講座のおすすめポイントを以下にまとめておきます。

当講座のおすすめポイント

シリコンバレーで働いているということもあり、講師のPythonの知識が豊富

話も適度な速さで聞き取りやすい

コードの意味だけでなく、それをどう応用するかまで解説してくれる

なお、Udemyについては以下の記事でまとめていますのでご参考ください。

まとめ

ということで、今回はシステム開発時に役立ちそうなPythonのファイル操作について解説しました。
ファイル操作は実際のアプリケーション開発において、ほぼほぼ必須の知識になってくるので、是非マスターしておくことで業務効率を上げたいですね。
では、今回はここまでとさせていただきます。