Your super
invocation is wrong: self
should not be supplied again, it's already injected by super
. This way, file_error.args[0] is file_error
because you pass self
as an extra argument to the exception constructor. This should make it obvious why fix #1 (removing the super call altogether) helps, but of course the best fix is to pass the right arguments:
super(FileError, self).__init__(filename, *a, **k)
The reason for the infinite recursion: First off, only object.__str__
delegates to __repr__
; BaseException
defines both __str__
and __repr__
separately, so str()
of an exception calls that overload, not your __repr__
. BaseException.__str__
usually prints the args tuple (which would use repr
), though when it contains a single argument, it prints the str()
of that single argument.
This invokes BaseException.__str__
again, and so on. Fix #2 prevents this cycle by not entering BaseException.__str__
in the first place, instead using your __repr__
which does not touch the args tuple at all.