1次ディレクトリーとはテストファイルの作成などの際に、その実装の間だけ作成され、テストが終了するときには削除されるディレクトリー。容量が多くならないのでいい。

with ... 文で使うと作った一時ディレクトリーを削除する必要がなくなり便利です。

 

1次ファイルの作成の流れ



①実例
import tempfile  ※呼び出し方
import unittest

from counter import count_file_lines

class TestCountFileLines(unittest.TestCase):
    def test_count(self):
        with tempfile.NamedTemporaryFile(mode="w") as f: ※1次ファイルを作成している
            f.write("""one
two
three
four
""")
            
            f.flush()
            actual = count_file_lines(f.name)
        self.assertEqual(actual, 4)

解説
・with ... 内で使うと、作られた一時ファイルも自動で削除されるので便利です。
 

・mode="w" 引数でファイルに文字列で書き込むように指定しています。こうすると f.write("...") のように文字列を書き込めます。
 

・f.flush() は書き込み用のバッファから確実にファイルへの書き込みを実行させる処理です。

 通常 flush はファイルクローズ時に必ず実行されます。しかし、ここでは open したファイルに書き込み後クローズせずに「 関数 count_file_lines 内で同一ファイルを別途 open」しています。この場合、書き込みは反映されないことがあります。明示的に f.flush() を呼ぶことで書き込みを反映し、count_file_lines内で書き込んだ内容を取得できるようになります。
 

・actual = count_file_lines(f.name)では、一時ファイルの内容の行数をactualに代入しています。
 

・f.flush()を呼ばないと、正しい行数が取得できません。
 

・f.name から、作った一時ファイルへのファイルパスが取得できます。
 

・withの外では、一時ファイルは削除されており行数をカウントできません。


実例2  ※1次ファイルを複数作成する場合
import os
import tempfile
import unittest

from dircounter import count_files


class TestCountFiles(unittest.TestCase):
    def test_count(self):
        with tempfile.TemporaryDirectory() as dirpath:  ※ここで1次ディレクトリー作成
            with open(os.path.join(dirpath, "file1"), mode = "w", encoding= "utf-8") as f1, \
                        open(os.path.join (dirpath, "file2"), mode = "w", encoding = "utf-8") as f2:
                
                actual = count_files(dirpath)
        
        self.assertEqual(actual, 2)


解説
tempfile.TemporaryDirectory を使って一時ディレクトリーを作っています。

https://images.pyq.jp/repo/prod/unittest_tempfile/tmpdir.jpg

with ... 文で使うと作った一時ディレクトリーを削除する必要がなくなり便利です。

ディレクトリー内にファイルを作るには通常どおり、 open(... mode="w") を使います。

コラム
②同時に複数のファイルを開きたい場合、下記のように記述します。

with open(...) as f1, open(...) as f2:
    ...
しかし、横に長くなりすぎる場合は、改行した方が見やすいでしょう。
Pythonは改行で文を区切るので、「改行後も同じ文である」ことを示すために、下記のようにバックスラッシュを用います。

with open(...) as f1, \
        open(...) as f2:
    ...