tag:crieit.net,2005:https://crieit.net/tags/unittest/feed 「unittest」の記事 - Crieit Crieitでタグ「unittest」に投稿された最近の記事 2022-03-13T17:20:40+09:00 https://crieit.net/tags/unittest/feed tag:crieit.net,2005:PublicArticle/18152 2022-03-13T17:19:46+09:00 2022-03-13T17:20:40+09:00 https://crieit.net/posts/Python-unittest-ResourceWarning-unclosed-file Pythonのunittest実行時に、「ResourceWarning: unclosed file」が発生する場合の対処方法 <p>Pythonでunittestを実行していた際に、「ResourceWarning: unclosed file」が出力されたので、その対処方法について、記載。</p> <pre><code>global logins def log_setting(log_level): global logins home = '<ログファイルパス>' pid = os.getpid() # create logger logins = logging.getLogger(__name__) logins.setLevel(logging.DEBUG) # create File Handler fh = logging.FileHandler('{0}/log/log{1}.log'.format(home, pid)) fh.setLevel(logging.INFO) # create Formatter fh_formatter = \ logging.Formatter( '%(asctime)s - %(levelname)s - \ %(filename)s - %(name)s - %(funcName)s - %(message)s') # set Formatter fh.setFormatter(fh_formatter) # add Handler logins.addHandler(fh) # test logging logins.info('logtest:addHandler') </code></pre> <p>↑みたいな関数があり、unittest側からは下記でテストメソッド単位で呼び出したとする。</p> <pre><code>def setUp(self): logtest.log_setting(logging.DEBUG)` def tearDown(self): logtest.logins.handlers = [] </code></pre> <p>この場合、unittestを実行すると、ログファイル内に「ResourceWarning: unclosed file」が出力される。<br /> 理由はログファイルがクローズされていない状態で、ハンドラをクリアしているから。<br /> ハンドラをクリアしている理由は、そうしないとテストメソッドの実行の都度、「log_setting」が呼び出されてハンドラが追加され、ログが重複して出力されてしまうから。</p> <p>ログファイルをクローズする処理を入れればいいので、下記のようにする。</p> <pre><code>def tearDown(self): logtest.logins.handlers[0].close() logtest.logins.handlers = [] </code></pre> <p>こうすると、ログファイルをクローズした後にハンドラをクリアするので、警告は出力されない。<br /> ログも重複しない。</p> <p>本当にいいのは、テスト対象側のプログラムを修正することだと思う。<br /> ファイル出力しかしない想定であれば、addHandlerを使う必要はなく、下記で対応ができる。↓のほうがコード短いし、↑よりもいいかな。</p> <p>```<br /> def log_setting(log_level):<br /> global logins<br /> home = '/home/aoiro/work/logtest'<br /> pid = os.getpid()</p> <pre><code># create logger logins = logging.getLogger(__name__) log_format = \ '%(asctime)s - {} - %(levelname)s - %(message)s'.format("tester") logging.basicConfig( filename='{0}/log/log{1}.log'.format(home, pid), level=log_level, format=log_format) </code></pre> <p>```</p> ao-iro