2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PythonAdvent Calendar 2023

Day 15

Pythonのファイルアクセスから圧縮・解凍まで。

Last updated at Posted at 2023-11-11

はじめに

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() ファイル全部読み込み、行ごとにリスト化。

テキストファイルの読み書きの例。

text_file.py
# ファイル書き込み(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_file.py
# 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が格納される。

enc_type.py
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使う。osremove()は空フォルダしか削除できない。

コマンド 内容
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:コピー先フォルダ

参考

dir_test.py
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を探索出力する例。

path_test.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:解凍先フォルダ名

参考

targz_test.py
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')

戻る

以上

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?