1. 概要
「python」のプログラムを実行していて、いきなり
AttributeError: '変数やらクラスやら' object has no attribute '変数やらメソッドやら'
てなエラーで落ちることがあります。
本ページは、下記のサイトを参考にさせていただきました。
「組み込み関数」
「Python で Object Has No Attribute エラーを修正する」
「【Python】AttributeError」
「[python]「AttributeError: module(object) ‘xxx’ has no attribute ‘yyy’」が起きたときの対処法5選」
2. どういうことか
要は、その変数なりオブジェクトなりが、落ちる元となった変数やメソッドに対応する属性を持ち合わせていませんよと言っておるわけです。
ま、仮に
l = 'a'
l.append('b')
てなソースを書いて、実行すりゃ
Traceback (most recent call last):
File "/home/hogehoge/lang/python/test/test04.py", line 2, in <module>
l.append('b')
AttributeError: 'str' object has no attribute 'append
となるのは、当然わかるわけで。
「list」型でなく、「str」なので、「append」なんてものはできませんよ。
なんてのは、「python」初心者の馬鹿のわたしでもわかるってもんです。
変数名やメソッド名を間違えたり、型を勘違いしてるなんてのは、ソースをちょっとじっくり眺めれば、わかります。
さて、問題なのが、自前のクラスで、一定の条件によって付ける属性があったりなかったりするようなことが・・・。
あなたは、ないか?
わたしは、あるのだ。
ソースの一部分を書きますが・・・。
contents.contents[childuri] = childcontents.contents
return contents.contents
てなソースを実行していたときに
AttributeError: 'Contents' object has no attribute 'contents'
ちゅうて落ちたんですな。
身に覚えはある。
ここで使用している「contents」ちゅうのが「contents」を持っておったり、いなかったりするのです。
さて。困ったぞ・・・と。
3. 解決策① dir
ま、単に型を間違えたりしている場合は、なおしてくだされ。
問題は、属性を持っていたり、持っていなかったりする場合・・・。
もちろん「try」「except」で例外処理を各方法もあるのですが・・・。
例外処理とは、別の方法がないかいな?・・・と。
参考サイトに、なるほどいう情報がありました。
属性の一覧を「dir」で見れるんですって。
こいつを知らなかったなぁ。この辺が、わたしの初心者だったり、馬鹿だったりするところですな。
で、わたしの解決法としては
contents.contents[childuri] = childcontents.contents
if ('contents' not in dir(contents)):
return None
return contents.contents
と書くことでした。
もちろん、呼び出し側で、「None」が戻ってきたときの処理を実装しておくことが条件になりますが・・・。
わたしの場合、上記のやり方で、思い通りに動かすことができました。
4. 解決策② hasattr
解決策のもう一つとして、「hasattr」という組み込み関数を使います。
hasattr(object, name)
マニュアルには
引数はオブジェクトと文字列です。文字列がオブジェクトの属性名の一つであった場合 True を、そうでない場合 False を返します。 (この関数は、 getattr(object, name) を呼び出して AttributeError を送出するかどうかを見ることで実装されています。)
と書いてあります。
これは、「request.urlopen」を使用していた時に、使いました。
「URL」をオープンしたときの例外の処理で
except (HTTPError, URLError, ConnectionResetError, timeout) as ex:
if ex.code == 403:
処理
てなことを書いて、「HTTP Error 403: Forbidden」のときの処理を記述しておったんですが。
「timeout」なんかは、「code」を持たないのですな。
この場合。
except (HTTPError, URLError, ConnectionResetError, timeout) as ex:
if hasattr(ex, 'code'):
if ex.code == 403:
処理
と書くことで、「AttributeError」は、起きなくなりました。