中学社会668760 views
高校倫理1440106 views
りんご209490 views
雑学1473612 views
英語613639 views
Computer368106 views
高校物理160203 views
中学理科1630641 views
世界の国564520 views
LaTeX962153 views
Help
Tools
NewsSpreadsheetCalendarSlidesTier ListPen ToolIllustrationCrayonPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchSwirl EffectOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsCross SectionsMotion PathMechanicsWavesElectromagnetic WavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHPeriodic TableComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseMuscle ContractionRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic TheoryShogi StrategyPiano Rhythm Game

English

Python の __exit__ で例外を処理する

__exit__() メソッドは、with ブロック内で発生した例外の情報を受け取ります。この情報を使って、例外を処理したり、ログを記録したり、例外を抑制したりできます。

exit の引数

__exit__() は3つの引数を受け取ります。

def __exit__(self, exc_type, exc_val, exc_tb):
    pass
exc_type

例外のクラス(型)。例外がなければ None。

exc_val

例外のインスタンス(値)。例外がなければ None。

exc_tb

トレースバックオブジェクト。例外がなければ None。

例外情報の確認

例外が発生したかどうかは、exc_typeNone かどうかで判断できます。

class ExceptionLogger:
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is None:
            print("正常終了")
        else:
            print(f"例外発生: {exc_type.__name__}: {exc_val}")
        return False

# 正常終了の場合
with ExceptionLogger():
    print("処理中")
# 処理中
# 正常終了

# 例外発生の場合
with ExceptionLogger():
    raise ValueError("エラーです")
# 例外発生: ValueError: エラーです
# (その後 ValueError が再送出される)

例外の抑制

__exit__()True を返すと、例外が抑制されて外部に伝播しません。

class SuppressError:
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is ValueError:
            print(f"ValueError を抑制: {exc_val}")
            return True  # 例外を抑制
        return False  # その他の例外は再送出

with SuppressError():
    raise ValueError("無視される")
print("処理継続")
# ValueError を抑制: 無視される
# 処理継続
return True

例外を抑制する。with ブロックの外には伝播しない。

return False(またはなし)

例外を再送出する。with ブロックの外に伝播する。

特定の例外のみ処理

例外の型をチェックして、特定の例外だけを処理することもできます。

class HandleFileError:
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is FileNotFoundError:
            print(f"ファイルが見つかりません: {exc_val}")
            return True
        elif exc_type is PermissionError:
            print(f"権限がありません: {exc_val}")
            return True
        return False  # その他の例外はそのまま

with HandleFileError():
    open("存在しないファイル.txt")
print("処理継続")
# ファイルが見つかりません: [Errno 2] No such file or directory: '存在しないファイル.txt'
# 処理継続

クリーンアップは必ず実行される

例外を抑制するかどうかに関わらず、__exit__() 自体は必ず呼び出されます。

class CleanupDemo:
    def __enter__(self):
        print("リソース確保")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("リソース解放")  # 例外があっても実行される
        return False

try:
    with CleanupDemo():
        raise RuntimeError("エラー")
except RuntimeError:
    print("例外をキャッチ")

# リソース確保
# リソース解放
# 例外をキャッチ

注意点

例外を抑制する場合は慎重に行いましょう。予期しない例外まで抑制してしまうと、バグの発見が困難になります。通常は特定の例外のみを抑制し、それ以外は再送出するのが安全です。