ファイル操作の基礎からファイル周りのコードを簡潔に書くための実践的なテクニックを紹介します。また、Pythonの最新バージョンで取り入れられてた便利な機能(makedirsのexist_ok)などもあるためPythonに慣れた人も必見の内容です。
目次
ファイルを開く、作成する
open()関数を利用し、ファイルへのアクセスを行います。
第一引数にアクセスしたいファイルのパスを渡し、
第二引数にファイルモードを指定します。
ファイルは処理を行ったときにcloseで閉じるようにしましょう。
- r : 読み込み(デフォルト)
- w : 書き込み
- x : 書き込み(ファイルが存在しないことを確認)
- a : 追記書き込み
- + : 書き込みと読み出しの両方
- t : テキストモード (デフォルト)
- b : バイナリモード(画像などを書き出すときに使う)
>>> f = open('hoge.txt','w')
>>> #なんらかの処理を行う
>>> f.close()
withを使った書き方
with文で囲うことでcloseを省略できます。
こちらの書き方が一般的な書き方です。
>>> with open('hoge.txt', 'w') as f:
... f.write('hogehogehogehoge')
テキストモードの補足
テキストモードは、
sys.getdefaultencoding()の文字コードを
利用してファイルを開きます。
Python3の場合は、一般的にutf-8が設定されています。
それ以外の文字コードのファイルを開く場合は
openの引数に適切な文字コードを渡す必要があります。
また、Python2で日本語のファイルを開く場合は、
バイナリモードで開くか、utf-8を指定するのが無難です。
>>> f = open('hoge.txt', encoding='utf-8')
>>> #なんらかの処理を行う
>>> f.close()
ファイル読み込みのTips
ファイルからテキストを読み込む
ファイルからテキストを読み込む場合、
read()メソッドを利用することで可能です。
read(10)のように引数に値を渡すことで文字数を指定することもできます。
使用例
>>> f = open('hoge.txt', encoding='utf-8')
>>> print(f.read())
ほげほげほげほげほげほげほげ
>>> f.close()
ファイルから1行ごとに読み込む
openの戻り値はイテレータでもあるので、
次のようにファイルから1行ずつ読み取ることが可能です。
使用例1
>>> f = open("hoge.txt", encoding="utf-8")
>>> for line in f:
... print(line)
...
ほげ1
ほげ2
ほげ3
ほげ4
f.close()
使用例2
readline()メソッドを利用することでも可能です。
>>> f = open('hoge.txt', encoding='utf-8')
>>> for line in f.readlines():
... print(line)
...
ほげ1
ほげ2
ほげ3
ほげ4
>>> f.close()
ファイル書き込みのTips
テキストを書き込む
ファイルにテキストを書き込む場合、
write()メソッドを利用することで可能です。
“w”モードでファイルを開いた場合、
ファイルに書き込まれているデータは消えます。
また、ファイルが無い場合、新たに作成されます。
使用例
>>> f = open('hoge.txt', 'w', encoding='utf-8')
>>> f.write('ほげほげほげ')
6
>>> f.close()
printでファイルに書き込む
また、printメソッドを利用して書き込む方法もあります。
>>> f = open('hoge.txt', 'w', encoding='utf-8')
>>> print('hoge',file=f)
>>> f.close()
バイナリファイルを書き込む(動画や画像など…)
write()メソッドで動画や画像などのバイナリデータを書き込むこともできます。
その場合は、バイナリモードでファイルを開く必要があります。
>>> f = open('hoge.jpg', 'wb')
>>> f.write(img)
>>> f.close()
ファイルが存在しない場合は書き込む
存在するファイルをwモードでファイルを開いた場合、
内容が消えてしまうため危険です。
意図しないデータの消去を避けるために
xモードがPythonでは用意されています。
これは、ファイルが存在する場合、
例外をなげるようになっているため安全です。
>>> f = open('hoge.txt', 'x', encoding='utf-8')//ファイルが存在する
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileExistsError: [Errno 17] File exists: 'hoge.txt'
>>> f = open('fuga.txt', 'x', encoding='utf-8')//ファイルが存在しない
>>> f.write("fugafuga")
8
>>> f.close()
ファイルパスのTips
ファイルパスはos.path
のメソッドを利用する方法と、pathlib
インスタンスを利用する方法があります。
どちらを使うかは基本的には好みの問題ですが、pathlib
のほうが人気のある印象です。
連続してパス操作やファイル操作をする場合はとくに便利です。
ファイル名を取得
import os
os.path.basename(path)
pathlib
の使用例
>>> from pathlib import Path
>>> p = Path(r"C:\Users\hoge\Desktop\hoge.txt")
>>> p.name
'hoge.txt'
ディレクトリ名を取得
import os
os.path.dirname(path)
pathlib
の使用例
>>> from pathlib import Path
>>> p = Path(r"C:\Users\hoge\Desktop\hoge.txt")
>>> p.parent
'hoge.txt'
ディレクトリ内のファイル一覧を取得 (ファイル名)
import os
dir_name = "hoge/"
file_pathes = os.listdir(dir_name)
パターンマッチで取得する
import glob
dir_name = "hoge/"
file_pathes = glob.glob(dir_name + "/*")
glob.glob
のほうがos.listdir
に比べて汎用性が高いのでおススメです。
ディレクトリ内のファイル一覧を取得 (絶対パス)
import glob
dir_name = os.path.abspath("hoge/")
file_pathes = glob.glob(dir_name + "*")
ファイルをパターンマッチで取得
glob.glob
を利用するとパターンにマッチするファイルが取得できます。
次のコードはhoge配下のcsvのファイル一覧を取得しています。
import glob
file_pathes = glob.glob("hoge/*.csv")
パスを作成
import os
os.path.join("hoge", "fuga", "hoge.txt")
pathlib
の使用例
pathlibを使うとPathオブジェクトの/
演算子がパスのjoinになっています。また、Pathオブジェクト同士だけではなくstr
ともjoinすることができます。
>>> from pathlib import Path
>>> str(Path("hoge")/"fuga"/"hoge.txt")
'hoge\fuga\hoge.txt'
~をホームディレクトリに展開
import os
os.path.expanduser("~/Desktop")
pathlib
の使用例
>>> from pathlib import Path
>>> p = Path(r"~/Desktop\hoge.txt")
>>> str(p.expanduser())
'C:\Users\hoge\Desktop\hoge.txt'
拡張子を分割
import os
os.path.splitext(path)
絶対パスを取得
import os
os.path.abspath(path)
使用例
>>> import os
>>> path = r"C:\Users\hoge\Desktop\hoge.txt"//rつけると\のエスケープが不必要
>>> os.path.basename(path)
'hoge.txt'
>>> os.path.dirname(path)
'C:\Users\hoge\Desktop'
>>> os.path.join(r"C:\Users\hoge","Desktop","hoge.txt")
'C:\Users\hoge\Desktop\hoge.txt'
>>> os.path.expanduser(r"~\Desktop\hoge.txt")
'C:\Users\hoge\Desktop\hoge.txt'
>>> os.path.splitext(path)
('C:\Users\hoge\Desktop\hoge', '.txt')
ファイル操作のTips
ファイル、ディレクトリの存在を確認
import os
os.path.exists(path)
使用例
import os
>>> os.path.exists('hoge.txt')
True
>>> os.path.exists('none.txt')
False
pathlib
の使用例
>>> from pathlib import Path
>>> p = Path(r"hoge.txt")
>>> p.exists()
True
>>> p = Path(r"none.txt")
>>> p.exists()
False
ディレクトリ、ファイル一覧を取得
os.listdir(path)
使用例
>>> import os
>>> os.listdir("hoge")
['fuga.txt', 'hoge.txt', 'hogedir']
パターンにマッチするディレクトリ、ファイル一覧を取得
glob.glob(pattern)
使用例
>>> import glob
>>> glob.glob('hoge/*.txt')
['hoge\fuga.txt', 'hoge\hoge.txt']
ファイル、ディレクトリの種類を確認
ファイルかを確認
os.path.isfile(path)
ディレクトリかを確認
os.path.isdir(path)
シンボリックリンクかを確認
os.path.islink(path)
シンボリックリンクの本来のパスを確認
os.path.isrealpath(path)
使用例
>>> import os
>>> os.path.isfile('hoge.txt')
True
>>> os.path.isdir('hoge.txt')
False
>>> os.path.islink('/usr/local/bin/python3')
True
>>> os.path.realpath('/usr/local/bin/python3')
'/usr/local/bin/python3.3'
ディレクトリを作成
os.mkdir()
使用例
import os
>>> os.mkdir('hoge1')
>>> os.mkdir('hoge1')
Traceback (most recent call last):
File "", line 1, in
FileExistsError: [Errno 17] File exists: 'dir1'
ディレクトリをまとめて作成
os.makedirs()
使用例&mkdirとの比較
mkdirでディレクトリを作成する場合、親のディレクトリが存在してなければFileNotFoundError
が発生します。いちいち、親のディレクトリを作成するのは面倒です。そこでmakedirsが役立ちます。
import os
>>> os.path.exists('hoge1')
## False
>>> os.mkdir('hoge/fuga')# hogeが存在しないのでエラー
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 3] 指定されたパスが見つかりません。: 'hoge/fuga'
>>> os.makedirs('hoge/fuga')# makedirsだと作成できる
makedirsのexist_okが便利(Python3.2以降)
Python3.2以降のmakedirsはexist_okという便利な引数があります。これは存在するディレクトリをmakedirsしてもエラーが発生しないフラグです。
これを使うことでディレクトリを存在するかどうかの確認を事前にする必要がなくなるため便利。コードもすっきりとします。
if not os.path.exists("hoge"):
os.makedirs("hoge")
このコードがexist_okを使うと以下のように書くことができます。
os.makedirs("hoge", exist_ok=True)
ファイル、空のディレクトリをコピー
shutil.copy(src,dest)
使用例
>>> import shutil
>>> shutil.copy("hoge.txt", "hoge1.txt")
ディレクトリを中身ごとコピー
>>> import shutil
>>> shutil.copytree("hoge", "hoge1")
'hoge1'
ファイルの削除
os.remove(path)
使用例
import os
>>> os.remove('hoge.txt')
>>> path.exists('hoge.txt')
False
空のディレクトリを削除
os.rmdir(path)
使用例
import os
>>> os.rmdir('hoge')
>>>
>>> os.rmdir('hoge')
Traceback (most recent call last):
File "", line 1, in
FileNotFoundError: [Errno 2] No such file or directory: 'dir1'
ディレクトリを中身ごと削除
shutil.rmtree(path)
使用例
>>> import shutil
>>> shutil.rmtree("hoge1")
ファイル、ディレクトリの移動
shutil.move(src,dest)
使用例
>>> import shutil
>>> shutil.move("hoge","fuga")