はじめに
Pythonでのファイルの読み書き、フォルダ操作、ファイルパス操作、フォルダの圧縮解凍をまとめる。
目次
ファイルの読み書き
ファイルの読み書きはopen()
を使用する。with
をセットで使うとclose()
を記載しなくてもファイルを閉じてくれるので便利。以降、withを使った方法で説明する。
# with文使わない場合
file=open('testfile.txt' ,mode='r' ,encoding='utf-8')
print(file.read())
file.close()
# with文使った場合
with open('testfile.txt' ,mode='r' ,encoding='utf-8') as file:
print(file.read())
ファイルの読み書きのモードはmode
、エンコーディングはencoding
で設定できる。
mode
読み込み | 内容 |
---|---|
mode='r' | 読み込み。 |
mode='rb' | バイナリモードで読み込み。 |
書き込み | 内容 |
mode='w' | 書き込み。ファイルがなければ新規作成。 ファイルが既にある場合は上書き。 |
mode='a' | 書き込み。ファイルがなければ新規作成。 ファイルが既にある場合は追記。 |
mode='r+' | 既存ファイルの先頭に書き込み。 |
mode='wb' | バイナリモードで書き込み。ファイルがなければ新規作成。 ファイルが既にある場合は上書き。 |
mode='ab' | バイナリモードで書き込み。ファイルがなければ新規作成。 ファイルが既にある場合は追記。 |
mode='r+b' | バイナリモードで既存ファイルの先頭に書き込み。 |
encoding
設定 | 内容 |
---|---|
encoding='utf-8' | utf-8 |
encoding='cp932' | cp932 |
encoding='shift-jis' | shift-jis |
読み書き関数
関数 | 内容 |
---|---|
file.read() | ファイル全部を読み込む。 |
file.readline() | ファイル1ライン読み込む。 |
file.readlines() | ファイル全部読み込み、行ごとにリスト化。 |
テキストファイルの読み書きの例。
# ファイル書き込み(mode='w')--------------------------------------
with open('testfile.txt' ,mode='w', encoding='shift-jis') as file:
string = 'あいうえお\n1234567890\nabcdefghij\nABCDEFGHIJ\n'
file.write(string)
# ファイル読み込み(mode='r')--------------------------------------
#read()
with open('testfile.txt' ,mode='r', encoding='shift-jis') as file:
file_data = file.read()
print(f'# {type(file_data)=} \n# {file_data=}')
# type(file_data)=<class 'str'>
# file_data='あいうえお\n1234567890\nabcdefghij\nABCDEFGHIJ\n'
#readline()
with open('testfile.txt' ,mode='r', encoding='shift-jis') as file:
file_data = file.readline()
print(f'# {type(file_data)=} \n# {file_data=}')
# type(file_data)=<class 'str'>
# file_data='あいうえお\n'
#readlines()
with open('testfile.txt' ,mode='r', encoding='shift-jis') as file:
file_data = file.readlines()
print(f'# {type(file_data)=} \n# {file_data=}')
# type(file_data)=<class 'list'>
# file_data=['あいうえお\n', '1234567890\n', 'abcdefghij\n', 'ABCDEFGHIJ\n']
# ファイル追記(mode='a')------------------------------------------
with open('testfile.txt' ,mode='a', encoding='shift-jis') as file:
string='アイウエオ\n'
file.write(string)
with open('testfile.txt' ,mode='r', encoding='shift-jis') as file:
file_data = file.readlines()
print(f'# {type(file_data)=} \n# {file_data=}')
# type(file_data)=<class 'list'>
# file_data=['あいうえお\n', '1234567890\n', 'abcdefghij\n', 'ABCDEFGHIJ\n', 'アイウエオ\n']
# ファイル先頭上書き(mode='r+')-----------------------------------
with open('testfile.txt' ,mode='r+', encoding='shift-jis') as file:
string='一二三四五'
file.write(string)
with open('testfile.txt' ,mode='r', encoding='shift-jis') as file:
file_data = file.readlines()
print(f'# {type(file_data)=} \n# {file_data=}')
# type(file_data)=<class 'list'>
# file_data=['一二三四五\n', '1234567890\n', 'abcdefghij\n', 'ABCDEFGHIJ\n', 'アイウエオ\n']
バイナリファイルの読み書き。
数値文字列バイナリ変換は<Pythonで数値・数値文字列・バイナリ変換>を参照。
# binaryファイル新規作成(mode='wb')-----------------------------------
with open('testfile.bin' ,mode='wb') as file:
hex_string='0102030405060708'
file.write(bytes.fromhex(hex_string))
# binaryファイル読み込み(mode='rb')-----------------------------------
with open('testfile.bin' ,mode='rb') as file:
file_data = file.read()
print(f'# {type(file_data)=} \n# {file_data=}')
# type(file_data)=<class 'bytes'>
# file_data=b'\x01\x02\x03\x04\x05\x06\x07\x08'
# binaryファイル追記(mode='ab')----------------------------------------
with open('testfile.bin' ,mode='ab') as file:
hex_string='AAAA'
file.write(bytes.fromhex(hex_string))
with open('testfile.bin' ,mode='rb') as file:
file_data = file.read()
print(f'# {type(file_data)=} \n# {file_data=}')
# type(file_data)=<class 'bytes'>
# file_data=b'\x01\x02\x03\x04\x05\x06\x07\x08\xaa\xaa'
# binaryファイル先頭上書き(mode='r+b')--------------------------------
with open('testfile.bin' ,mode='r+b') as file:
hex_string='EEEE'
file.write(bytes.fromhex(hex_string))
with open('testfile.bin' ,mode='rb') as file:
file_data = file.read()
print(f'# {type(file_data)=} \n# {file_data=}')
# type(file_data)=<class 'bytes'>
# file_data=b'\xee\xee\x03\x04\x05\x06\x07\x08\xaa\xaa'
ファイルの文字コード判別
読み込むファイルとencodingがあっていないとエラーが発生するため、文字コードを事前に判定必要。charedt.detect()
を使えば判定可能。ファイルをバイナリモードで読み込み、そのバイナリデータをcharedt.detect(<バイナリ>)
へ設定し判定する。戻り値が、辞書型で返答され、keyのencodingにタイプが格納される。エンコード判定の結果、バイナリファイルであれば、None
が格納される。
import chardet
# encodingタイプを確認
test_file = 'testfile.txt'
with open(test_file ,mode='rb') as file:
enc_type = chardet.detect(file.read())
print(f'# {type(enc_type)=} / {enc_type=}')
# type(enc_type)=<class 'dict'> / enc_type={'encoding': 'SHIFT_JIS', 'confidence': 0.99, 'language': 'Japanese'}
# enc_type['encoding']にエンコードタイプが格納される、バイナリファイルなら None判定
if enc_type['encoding'] != None:
with open(test_file ,mode='r',encoding=enc_type['encoding']) as file:
print(file.read())
else:
print(f'{test_file}はbinaryファイルです。')
参考
フォルダ操作
フォルダの作成はos
ライブラリを、削除はshutil
使う。os
のremove()
は空フォルダしか削除できない。
コマンド | 内容 |
---|---|
os.makedirs(dir_name, exist_ok=True/False) | フォルダの作成 dir_name:作成するフォルダ名 exist_ok=:Trueにするとフォルダが既に存在した場合でも処理が進む。 |
shutil.rmtree(dir_name) | 配下のサブフォルダ、ファイル含め削除。削除されたものは復活できないので使う時は注意。 dir_name:削除するフォルダ |
shutil.move(src_dir, dst_dir) | 配下のサブフォルダ、ファイル含め移動。 src_dir:移動元フォルダ dst_dir:移動先フォルダ |
shutil.copy2(src_file,dst_dir) | ファイルをメタデータ含めコピー。 src_file:コピー元ファイル dst_dir:コピー先フォルダ |
shutil.copytree(src_dir,dst_dir) | フォルダ配下ごと再帰的にコピー。 src_dir:コピー元フォルダ dst_dir:コピー先フォルダ |
参考
import os
import shutil
# 削除
yn=input(f'test_dir フォルダを削除してよいですか? y or n')
if yn=='y':
shutil.rmtree('test_dir')
# 作成
os.makedirs('test_dir',exist_ok=True)
os.makedirs('test_dir/dirA/move_dir',exist_ok=True)
os.makedirs('test_dir/dirB',exist_ok=True)
for i in range(100):
with open(f'test_dir/dirA/move_dir/test{i:03}.txt',mode='w') as file:
file.write('test')
# 移動 dirA→dirB
shutil.move('test_dir/dirA/move_dir', 'test_dir/dirB')
# コピー dirB→dirA
shutil.copytree('test_dir/dirB','test_dir/dirA/move_dir')
#ファイルコピー
shutil.copy2('test_dir/dirB/move_dir/test000.txt','test_dir/dirA')
ファイルパス操作
ファイルパスの操作もos
ライブラリを使って操作できる。
コマンド | 内容 |
---|---|
os.getcwd() | カレントフォルダを出力する。 |
os.walk() | パスを出力するgenerator関数。 カレントフォルダ、サブフォルダリスト、ファイルリストを順次出力する。 |
os.path.join() | パスを結合する。 |
現在のフォルダ配下のサブフォルダ、ファイルをリストに出力する例と、出力したファイルリストから、拡張子が.pyを探索出力する例。
import os
import re
#現在のフォルダ-------------------------------
print(f'{os.getcwd()=}')
# サブフォルダ、ファイルリストを出力-----------
dir_list=[] # サブフォルダリスト出力用
file_list=[] # ファイルリスト出力用
for Dir, Subdirs, Files in os.walk(os.getcwd()):
#dir_list:サブフォルダリスト作成
for s in Subdirs:
dir_list.append(os.path.join(Dir,s))
#file_list:ファイルリスト作成
for f in Files:
file_list.append(os.path.join(Dir,f))
# 拡張子が'.py'を出力-------------------------
for i in file_list:
if re.search(r'.*.py$',i):
parent =i[:i.rfind('\\')] #スライスで最後の\より前のparentパスを出力
reaf =i[i.rfind('\\')+1:] #スライスで最後の\より後のreafを出力
print(f'# Path:{i}\n# Dir :{parent}\n# File:{reaf}')
フォルダの圧縮解凍
tar.gzファイルに圧縮、解凍する際は、tarfile
を使う。
コマンド | パラメータ |
---|---|
with tarfile.open(filename, 'w:gz') as tar: tar.add(comp) |
filename:圧縮後ファイル名 comp:圧縮対象 |
with tarfile.open(filename) as tar: tar.extractall(decomp) |
filename:解凍ファイル名 decomp:解凍先フォルダ名 |
参考
import os
import tarfile
#作成('targz_test_dir'フォルダに100ファイル作成)
dir_name='targz_test_dir'
os.makedirs(dir_name,exist_ok=True)
for i in range(100):
file_name = f'{dir_name}/test_{i:03}.txt'
with open(file_name,mode='w') as file:
file.write(file_name)
#tar.gz圧縮(targz_test_dir.tar.gz というファイル名で圧縮)
tar_name = 'targz_test_dir.tar.gz'
with tarfile.open(tar_name, 'w:gz') as tar:
tar.add(dir_name)
#tar.gz解凍('decomp'フォルダに解凍)
with tarfile.open(tar_name) as tar:
tar.extractall('decomp')
以上