【Python】SimplePrograms line 9 ファイルアクセスと「with」ブロック
プログラム
9行プログラムです。
# indent your Python code to put into an email
import glob
# glob supports Unix style pathname extensions
python_files = glob.glob('*.py')
for file_name in sorted(python_files):
print (' ------' + file_name)
with open(file_name) as f:
for line in f:
print (' ' + line.rstrip())
実行結果
------binary_sequence.py
a = b'ab cdef'
print('type of a is' , type(a))
for item in a:
print(item)
------line9.py
# indent your Python code to put into an email
import glob
# glob supports Unix style pathname extensions
python_files = glob.glob('*.py')
for file_name in sorted(python_files):
print (' ------' + file_name)
with open(file_name) as f:
for line in f:
print (' ' + line.rstrip())
print()
------set.py
a = {1, 2, 3}
print('type of a is' , type(a))
for item in a:
print(item)
------text_sequence.py
a = 'ab cdef'
print('type of a is ' , type(a))
for item in a:
print(item)
解説
2、4行目 UNIXスタイルのファイル指定
ファイルアクセスです。
コメントは飛ばして、2行目と4行目。
import glob
python_files = glob.glob('*.py')
「glob」は、コメントにある通り「UNIXスタイルのファイル指定を可能にするライブラリ」です。「glob」というのはUNIX時代からの呼び名であるらしい。UNIX手法の踏襲は未だに多く見られます。「glob」は「グローバル・コマンド」の略称とのこと。ネーミングそのものがグローバルですが、定着してしまったのでしょう。
「glob」ライブラリの「glob」を呼び出して、カレントディレクトリの下にある「.py」に該当するファイルのファイル名を取り出しています。UNIXにおいて「*」はワイルドカードで、任意の長さの文字列を意味します。ですからこれは「.py」で終わる文字列のことになります。
この「glob.glob」の戻り値の型はなんでしょうか。
>>> import glob
>>> python_files = glob.glob('*.py')
>>> type(python_files)
<class 'list'>
>>>
「list」型ですね。
ちなみに中身を表示してみると、ファイル名が文字列で設定されています。
>>> print(python_files)
['line5.py', 'line7.py', 'binary_sequence.py', 'text_sequence.py', 'set.py', 'line9.py']
>>>
5行目 for文(ファイルリスト)
for file_name in sorted(python_files):
「sorted」をなしにすると、こうなります。
for file_name in python_files:
「python_files」にはファイル名が1つずつ入っていますから、そのファイル名を1つずつ順番に処理することになります。
「sorted」を潜らせると、そのファイル名が並べ替えられることになります。
「sorted」するかしないかで、次のように変わります。
>>> print(python_files)
['line5.py', 'line7.py', 'binary_sequence.py', 'text_sequence.py', 'set.py', 'line9.py']
>>> print(sorted(python_files))
['binary_sequence.py', 'line5.py', 'line7.py', 'line9.py', 'set.py', 'text_sequence.py']
>>>
6行目
ここからは「for」文の中になります。
print (' ------' + file_name)
これは、ファイル名を表示しているだけですね。
7行目 withブロック(open)
with open(file_name) as f:
「with」。
また、新しいキーワードだな。
これも、C言語にはなかったものですね。
VBにも「with」はあったけど、少し違うように見えます。
「with」というのは、「open/close」や「lock/unlock」など、後片付けが必要な処理をパッケージ化するためのものだそうです。
そう、このコードに「close」はないですね。
「with」ブロックを抜ける時に、自動的にクローズされることになります。
「with」ブロックなしで書いてみる
「with」を使うと「close」忘れという問題がなくなっていいのだけど、時には「オープンしたまま」というような使い方もしないではない。
「open」は「with」ブロックなしでも使えるのかな。
試してみた。
「with」ブロックなしでももちろん使えるようだ。
コード
f = open('set.py')
print('id(f) = ', id(f))
print('type(f) =', type(f))
print('f.name =', f.name)
print('f.closed =', f.closed)
print()
def show_py():
print (' ------ show_py')
print('id(f) = ', id(f))
print('type(f) =', type(f))
print('f.name =', f.name)
print('f.closed =', f.closed)
print('f.tell() =', f.tell())
f.seek(0)
for line in f:
print (' ' + line.rstrip())
print()
show_py()
show_py()
f.close()
実行結果
id(f) = 4009287472
type(f) = <class '_io.TextIOWrapper'>
f.name = set.py
f.closed = False
------ show_py
id(f) = 4009287472
type(f) = <class '_io.TextIOWrapper'>
f.name = set.py
f.closed = False
f.tell() = 0
a = {1, 2, 3}
print('type of a is' , type(a))
for item in a:
print(item)
------ show_py
id(f) = 4009287472
type(f) = <class '_io.TextIOWrapper'>
f.name = set.py
f.closed = False
f.tell() = 77
a = {1, 2, 3}
print('type of a is' , type(a))
for item in a:
print(item)
「with」ブロックを付けて書いてみる
前記のコードを「with」ブロックを付けて書いてみました。
やっぱり、クローズされてしまっているようです。
コード
with open('set.py') as f:
print('id(f) = ', id(f))
print('type(f) =', type(f))
print('f.name =', f.name)
print('f.closed =', f.closed)
print()
def show_py():
print (' ------ show_py')
print('id(f) = ', id(f))
print('type(f) =', type(f))
print('f.name =', f.name)
print('f.closed =', f.closed)
print('f.tell() =', f.tell())
f.seek(0)
for line in f:
print (' ' + line.rstrip())
print()
show_py()
show_py()
f.close()
実行結果
id(f) = 3867382704
type(f) = <class '_io.TextIOWrapper'>
f.name = set.py
f.closed = False
------ show_py
id(f) = 3867382704
type(f) = <class '_io.TextIOWrapper'>
f.name = set.py
f.closed = True
Traceback (most recent call last):
File "/storage/emulated/0/qpython/.last_tmp.py", line 20, in <module>
show_py()
File "/storage/emulated/0/qpython/.last_tmp.py", line 14, in show_py
print('f.tell() =', f.tell())
ValueError: I/O operation on closed file.
1|:/ $
8行目 ファイルから1行ずつ読み込み
for line in f:
ファイルから1行ずつ取り出しています。
「f.dir()」を実行してみると、「iter」も「next」も持っているようですから、イテラブルなオブジェクトのようです。
9行目
print (' ' + line.rstrip())
読み出した1行を出力します。
「rstrip」は、「strip」は取り除く、「r」は「right」右。右側の(行の末尾の)文字を取り除きます。引数で取り除く文字を指定しますが、指定がなければ空白を取り除きます。
「rstrip()」は、「行の末尾の空白を取り除く
」ということを意味します。