エラーメッセージが明確に、初心者もデバッグしやすく
最後に、Python 3.10から各バージョンで実施されてきたエラーメッセージの改良について紹介します。
より的確になったエラーメッセージ[3.10]
Python 3.10では、SyntaxError、IndentationError、NameError、AttributeErrorでより的確なエラーメッセージが出力されるようになっています。例えばSyntaxErrorですが、リストのようなコードはPython 3.9では以下のようなエラーメッセージが出力されていました。
expected = {1: 1, 2: 2, 3: 3,
a = func()
File "error_messages_310.py", line 3
a = func()
^
SyntaxError: invalid syntax
「invalid syntax=不正な構文」と出力されるだけなので、具体的に何が悪いのか分かりません。しかも、ハット(^)の場所を見ても構文エラーには見えないのも問題です。Python 3.10では、このような不親切なエラーメッセージが改善され、「'{' was never closed=中かっこが閉じていない」と、より具体的になりました。
File "error_messages_310.py", line 1
expected = {1: 1, 2: 2, 3: 3,
^
SyntaxError: '{' was never closed
エラーメッセージへのカラム位置出力[3.11]
Python 3.11におけるエラーメッセージの改良は、エラー発生箇所のカラム位置が表示されるようになったことです。Python 3.10までは、ゼロ除算時のエラーは以下のように素っ気ないものでした。エラーの発生と内容は分かりますが、具体的にどの変数が問題だったかなどの情報は得られません。
a = 1
b = 0
c = 1
print(a / b / c)
Traceback (most recent call last):
File "error_messages_311.py", line 4, in <module>
print(a / b / c)
ZeroDivisionError: division by zero
Python 3.11では、エラーメッセージこそ同じですが、エラーの発生箇所がハット(^)で示されるので、この場合は変数bでの除算に問題があったことが分かります。
…略…
print(a / b / c)
~~^~~
ZeroDivisionError: division by zero
改良されたNameErrorなどのエラーメッセージ[3.12]
Python 3.12では、NameErrorやSyntaxError、ImportErrorが発生していた局面で、エラーメッセージの内容がより具体的で親切になりました。例えばPython 3.11までは、インポートしていないモジュールを使おうとすると以下のように表示されていました。
print(sys.argv)
Traceback (most recent call last):
File "error_messages_312.py", line 10, in <module>
print(sys.argv)
^^^
NameError: name 'sys' is not defined
'sys'が未定義ということですが、sysがモジュールであることが分かれば修正は容易です。これが、Python 3.12では以下のように親切になります。
…略…
print(sys.argv)
^^^
NameError: name 'sys' is not defined. Did you forget to import 'sys'?
途中までは同じですが、「'sys'をimportするのを忘れてません?」と補足してくれます。これによって、知識があやふやな開発者でも「ああ、そうだった」とすぐに気付いて修正できるでしょう。また、インスタンス変数についても可能な限り推測を試みてくれます。例えば以下のリストのようなケースです。
class C:
def __init__(self):
self.var = 1
def method(self):
self.bar = var
C().method()
実行すると、methodメソッドの呼び出しでNameErrorとなりますが、「self.varじゃない?」というように補足してくれるので便利です。
Traceback (most recent call last):
File "error_messages_312.py", line 12, in <module>
C().method()
File "error_messages_312.py", line 10, in method
self.bar = var
^^^
NameError: name 'var' is not defined. Did you mean: 'self.var'?
この他にありがちなコーディングミスとして、from ... import ...のfromとimportを逆にしてしまったりしたときのSyntaxError、importする名前空間が見つからないときのImportErrorに対して、それぞれ以下のようなエラーメッセージを出力してくれます。
import Counter from collections^^^^^^^^ SyntaxError: Did you mean to use 'from ... import ...' instead? ImportError: cannot import name 'counter' from 'collections' (…/__init__.py). Did you mean: 'Counter'?
これらの改善で、特に入門者にとって格段にデバッグしやすくなったといえるでしょう。
まとめ
今回は、Python 3.10以降の新機能のうち、f-strings構文の機能強化、新しく導入されたExceptionGroupとTaskGroup、それに改良されたエラーメッセージを中心に紹介しました。
Pythonでは、このように魅力的な機能強化や改良が各バージョンで施されています。より使い勝手のよい言語として成長し続けるPythonを、今後も追っていきたいものです。
