Python テンポラリファイル

Python学習【365日チャレンジ!】99日目のマスターU(@Udemy11)です。

GWに【JIN -仁-】を観てから、漫画も読みたいなーと思っていたのですが、なかなか読むまでには至らなかったのですが、ようやく今日から読むことができるようになりました。

【JIN -仁-】は、すでに完結していて、漫画だと全20巻、2冊分が1巻にまとまったコンビニ用ペーパーバックだと全10巻でした。

特にコレクションしたいわけじゃないので、メルカリで全巻購入して、読み終えてからメルカリで出品すれば、電子書籍を購入したり、ブックオフで購入したりするより低価格で漫画を読むことができます。

なので、読みたい漫画はメルカリで購入して、読み終えてからメルカリで出品するようにしています。

タモリさんがやっているコマーシャルによると、日本人の10人に1人がメルカリをやってるらしいですよ。

メルカリ タモリ

まだメルカリをやっていないのなら、ぜひ試してみてください。

それではさっそくPython学習をはじめましょう!

昨日の復習

昨日は、zipファイルの圧縮と展開について学習しました。

2日続けて圧縮ファイルについて学習しましたが、tarファイルとzipファイルは同じような取り扱いができるものの、zipファイルのほうが圧縮する手間がかかったような感じでした。

import glob
import zipfile


with zipfile.ZipFile('test_zip.zip', 'w') as z
    for i in glob.glob('test_dir/**', recursive=True):
        r.write(i)

zipモジュールだけだと、ファイルもフォルダも一つずつ指定してwriteメソッドで書き込む必要がありましたが、フォルダ内のファイル名をパスを含めて取得することができるglobモジュールとforループを使うことで、コードを短くすることができました。

ファイルの展開については、tarファイル同様に、extractallメソッドを使って展開できましたが、extractfileメソッドは用意されていないので、展開せずに中のファイルを確認するには、openメソッドを使いました。

詳しくは、昨日のメソッドをごらんください。

それでは、今日の学習にはいりましょう!

tempfileモジュール

tempfileモジュールは、一時ファイルであるtemporaryファイルを扱うためのものです。

出入力のために一時的に記憶しておく【I/O(Input/Output)バッファ】にファイルを記録して、作業が終了したら削除したり、temporaryファイルを実際に作って、作業終了後に削除したりすることができます。

#temporary
import tempfile


with tempfile.TemporaryFile(mode='w+') as temp:
    temp.write('What is your name?')
    temp.seek(0)
    print(temp.read())

出力結果

What is your name?

TemporaryFileメソッドを使った場合は、【I/Oバッファ】に書き込まれます。

writeメソッドで、What is your name?と書き込んだあと、seek(0)で読み込み位置をもとに戻して、読み込んだものを出力しています。

出力まで終了すれば【I/Oバッファ】に記録されたデータが削除されます。

ファイルを削除せずに残す

次に、実際にファイルを作成して、削除せずにファイルを残す方法を学習します。

メモリのような【I/Oバッファ】に書き込むのではなく、ファイルを作成して、作成したファイルに書き込むメソッドがNamedTemporaryFileメソッドです。

デフォルトでは、作業が終了したあとファイルを削除する設定になっていますが、引数deleteFalseに指定することで作ったファイルを残しておくことができます。

import tempfile


with tempfile.NamedTemporaryFile(delete=False) as n:
    print(n.name)
    with open(n.name, 'w+') as f:
        f.write('How are you?')
        f.seek(0)
        print(f.read())

出力結果

/private/var/mobile/Containers/Data/Application/CCBA549E-E8FE-4616-A553-00250CF9575D/tmp/tmpcha_vur9
How are you?

5行目でprint(n.name)とありますが、n.nameでファイルのパスがわかります。

なので、6行目は、作られたファイルであるn.name'w+'で書き込み読み込みモードで開くということです。

あとは、【I/Oバッファ】に書き込んだときと同じコードですね。

4行目で引数deleteFalseを指定しているので、作業が終了したあとも、このファイルは存在しますので、確認してみましょう。

もちろん、openメソッドで、出力されたパスを指定して、readメソッドで読み込めば内容を確認することができますが、今回は、PythonistaのStaShを使って作られたファイルを確認してみます。

StaShについては、こちらのひとりぶろぐさんの記事を参考にインストールすることができますので、まだインストールされていない方は参考にどうぞ。

方法としては、先程のprint(n.name)の出力結果である/private/var/mobile/Containers/Data/Application/CCBA549E-E8FE-4616-A553-00250CF9575D/tmp/tmpcha_vur9をコピーします。

StaShを開いて(launch_stash.pyを開いて実行する)、catのあとに、半角スペースを入れて貼り付けたあと、【return】をタップすれば、次のような感じで出力されます。

Pythonista StaSh

この作業をしている時点でtempfileモジュールを使った作業は終了していますが、delet=Falseにしているので、ファイルが存在しているのが確認できます。

ここで私は、

マスターU

削除されなかったtempfileは、いつ削除されるんだろうか?

なんて気になったので調べてみると、Macの場合は再起動すると削除されるらしく、Windowsもアプリケーション終了時や再起動時には削除されるとのことでした。

そこで、iPhoneのアプリでもある【Pythonista】も再起動したら削除されるのかなと思って試してみたんです。

するとびっくり!ファイルはそのまま残っているではありませんか!

Pythonista StaSh

ま〜そのうち消えるような気もしなくはないのですが、気持ち悪いので削除してみることに。

まずは、cdコマンドでtmpフォルダに移動して、rmコマンドでファイルを削除してみました。

Pythonista StaSh

削除したあと、再びlsコマンドで確認してみると、きちんとファイルが削除されていました。

実は、Pythonistaの情報って、日本語だとあまり見つからなくて、ほとんどがインストールの仕方くらいしか見つからないので、自分でいろいろと試してみるしかないんですよね。

以前、コンソールのテキストの色を変更するサードパーティーのtermcolorライブラリをStaShを使ってインストールしたときは、きちんと動作していなかったので、悩んでかなり時間を費やしてしまいました。

今回の確認作業は、Linuxの標準コマンドを使うだけだったので、スムーズにできたのですが、ある程度コマンドやプログラムのコードに対してスキルが上がってきたのかなとも思っています。

tempフォルダ

tempfileモジュールはファイルだけじゃなく、フォルダ(ディレクトリ)も作成することができます。

import tempfile


with tempfile.TemporaryDirectory() as td:
   print(td)

出力結果

/private/var/mobile/Containers/Data/Application/CCBA549E-E8FE-4616-A553-00250CF9575D/tmp/tmpbwkpr0ta

フォルダを作るTemporaryDirectoryには、Namedから始まるメソッドは用意されていないので、引数deleteも用意されていませんが、フォルダを残したい場合には、別のメソッドが用意されています。

mkdtempメソッド

作業が終了したあとも作成したtempディレクトリを残しておくためのメソッドが、mkdtempです。

import tempfile


temp_dir = tempfile.mkdtemp()
print(temp_dir)

出力結果

/private/var/mobile/Containers/Data/Application/CCBA549E-E8FE-4616-A553-00250CF9575D/tmp/tmp3t7f38c5

Python公式ドキュメントには、使用後、ディレクトリと中身を削除しなければいけないと書かれているので、osモジュールをインポートして、os.rmdirで出力されたパスのディレクトリを削除するか、先程のtempファイルのときに削除した方法と同じようにStaShで削除しておきましょう。

削除したあと、Pythonファイルからディレクトリが存在するかどうかを確認するには、os.path.isdir('パスを貼り付け')を出力してみて、Falseが返ってくれば削除されています。

ファイルやフォルダを残す必要ある?

tempフォルダやtempファイルを削除してみて思うのは、

マスターU

自動で削除してくれるのに、わざわざ残しておく必要ある?

ってことです。

私と同じような疑問を持った酒井さんの講座の受講生もいたようで、その必要性について質問されていたのですが、その回答は、

ある処理を行ったあと、他の処理をして、最後にそのファイルを活用したいという場合に使うことがある

とのことでした。

これから、実践をしていく中で、そのようなコードを見かけるかもしれませんので、頭の片隅に残しておこうと思います。

そろそろ酒井さんのPython講座の入門編が終わりそうで、内容も随分と難しくなってきました。
過去のレクチャーを復習しつつ、実践に備えていこうと思います。

それでは、明日もGood Python!