問題

ここに移植する必要があるpython2のコードがあります:

 try:
  do_something_with_file(filename)

except:
  exc_type, exc_inst, tb = sys.exc_info()
  exc_inst.filename = filename
  raise exc_type, exc_inst, tb
 

上記のコードでは、例外に 'filename'属性があるかどうかをチェックして、問題のある入力ファイルで例外全体を取得できます。

しかし、python3のレイズは変更されました。これは2to3が上記のコードのために私に与えたものです:

 except Exception as e:
  et, ei, tb = sys.exc_info()
  e.filename = filename
  raise et(e).with_traceback(tb)
 

これは私に別のエラーを与え、私はfilename属性が保持されているとは思わない:

 in __call__
    raise et(e).with_traceback(tb)
TypeError: function takes exactly 5 arguments (1 given)
 

私が望むのは、入力ファイルを追跡するためにいくつかの情報で透過的に例外を渡すことです。私はpython2のraise [exception_type[,exception_instance[,traceback]]]が恋しい - どうすればpython3でこれを行うことができますか?

  ベストアンサー

__traceback__ 属性を設定することができます:

 except Exception as e:
    et, ei, tb = sys.exc_info()
    ei.filename = filename
    ei.__traceback__ = tb
    raise ei
 

または、古いインスタンスで.with_traceback()を直接呼び出します。

 except Exception as e:
    et, ei, tb = sys.exc_info()
    ei.filename = filename
    raise ei.with_traceback(tb)
 

しかし、トレースバックはすでに自動的にアタッチされています。

raise文のドキュメントを参照してください。

トレースバックオブジェクトは、__traceback__ 属性として例外が送出された際に自動的に作成されます。 これは書き込み可能です。

この特定のケースでは、おそらく文脈で別の例外が必要でしたか?

 class FilenameException(Exception):
    filename = None
    def __init__(self, filename):
        super().__init__(filename)
        self.filename = filename

try:
    something(filename)
except Exception as e:
    raise FilenameException(filename) from e
 

これにより、両方の例外がuncodeの場合に出力され、元の例外はnewexception.__context__として利用できます。

  同じタグがついた質問を見る

pythonpython-3.x