ソフトな忘却力(120) Python、Context managersでwith

Joseph Halfmoon

「サイエンティフィックPythonのための」IDE、Spyder上にてScientific Python Lecturesの実習中。Pythonの便利な構文に「with」あり。リソースの確保と開放を自動化してくれる構文。忘却力の老人にはありがたいもの。今回はwithできるオブジェクトを自前で作ってみるのだと。大丈夫か?

※「 ソフトな忘却力」投稿順 Index はこちら

※Sypder IDEはWindows版 6.0.8使用です。Python処理系はPython 3.11.13です。

Scientific Python Lectures様のコースは例題だけでなく、エクササイズなども充実、それを全部順番に解いていったら必ずや立派な人になれるだろ~と思います。でも老い先短い年寄には量が多過ぎて多分死ぬまでに終わりません。適当な練習でお茶を濁してます。今回は「7.3 Context managers」です。

コンテキストマネージャプロトコル

with構文を実現する仕組みは、「コンテキストマネージャ」プロトコルと呼ばれているみたいです。詳細は以下の公式ドキュメントに。

PEP 343 – The “with” Statement

「リソースの確保と開放を自動的かつ確実に行う仕組み」なんであります。別な説明としては「try..except..finally 構造の退屈な部分を別のクラスに抽出」し、「興味深い」部分だけに集中させてくれる仕組み、であるようです。

よくある「ファイルへの書き込み」などでは、以下のような形が多いかと

with open('ファイル名', 'モード') as 変数名:
    変数名.write("なんたら")

上記のような「file-likeオブジェクト」は勿論、lock、parallel programmingでも活躍する構文らしいデス。

このwith構文を利用するには、__enter__と__exit__というメソッドを実装したオブジェクト(context manager)が定義されていればよいみたい。

そこで、今回は殊更で空虚なcontext managerと、その中で扱われるなんちゃってなリソース部分を、自前定義し、ちゃんとwith 構文できることを確認したいと思います。

サンプル・プログラム

殊更で空虚なサンプルが以下に。dummyPrintは確保されるべきリソースです。self.statusがTrueのときだけ、正常に出力できるもの。sampleCMはそのリソースを管理するcontext managerです。__enter__にてステータスをTrueとし、__exit__にてステータスをfalseとしてます。

# -*- coding: utf-8 -*-
"""
Created on Thu Sep 25 13:45:35 2025

@author: J. Halfmoon
A Empty sample of the context manager
"""
class dummyPrint():
    def __init__(self, stat):
        self.status = stat
    
    def write(self, str):
        if self.status:
            print("OK", str)
        else:
            print("NG")   

class sampleCM(object):
    def __init__(self, dummy):
        self.obj = dummy
    
    def __enter__(self):
        self.obj.status = True
        return self.obj
    
    def __exit__(self, *args):
        self.obj.status = False

with sampleCM(dummyPrint(False)) as c:
    c.write("string 1")

c.write("string 2")

上記を実行した結果が、以下に。
ContextManagerTrialwithの内側では OK、そこを脱すると NG となるみたい。 こんなもんでいいのか?ちょっと無理やり、カッコよくない例題だな。。。

ソフトな忘却力(119) Pythonのデコレータで、while ループよけ へ戻る

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です