Pythonお悩み解決

Pythonに関する疑問や悩みにこたえるブログです

【エラー解説】NameErrorとは?原因と対応方法

今回はPythonNameErrorについて解説します。

1. NameErrorとは

NameErrorPythonの組み込み例外の1つで、「名前が見つからなかった」というエラーです。

このエラーは、変数や関数などを参照した際、その名前が見つからなかった場合に発生します。

いくつか発生ケースを見てみましょう。

以下は、Python 3.10で実行しています。

変数名が見つからない

>>> colors = ["red", "green", "blue"]
>>> color
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'color' is not defined. Did you mean: 'colors'?

関数名が見つからない

>>> def add_one(num):
...     return num + 1
...
>>> add_ona(10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'add_ona' is not defined. Did you mean: 'add_one'?

クラス名が見つからない

>>> class Animal:
...     def __init__(self, name):
...         self.name = name
...
>>> my_pet = Animel("ポチ")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Animel' is not defined. Did you mean: 'Animal'?

他にも発生ケースは考えられますが、いずれも「指定した名前が見つからない」ことが原因で発生します。

エラーメッセージの末尾に、Did you mean: 'colors'?のように間違えている名前の候補が表示されます。

これをヒントに、名前の指定が正しいかを確認するとよいでしょう。

ちなみに、エラーメッセージの末尾にあるDid you mean:以降の部分は、Python 3.10以降で表示されるようなりました。

Python 3.9以前では、以下のようにDid you mean:は表示されません。

>>> # Python 3.9 で実行した場合
>>> colors = ["red", "green", "blue"]
>>> color
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'color' is not defined

なお、NameErrorが発生するのは、ローカルまたはグローバルの名前が見つからなかった場合です。

辞書のキー名や、オブジェクトの属性名が見つからなかったには、別エラーが発生します(関連記事を参照)。

2. NameErrorの対応方法

NameErrorの原因は、タイプミスなど、単純なミスであることが多いです。

NameErrorが発生したら、指定した変数名や関数名が正しいかを確認しましょう。

3. まとめ

  • NameErrorは、参照した名前(変数名など)が見つからなかった場合に起きるエラー
  • NameErrorが発生したら、指定した名前が正しいかを確認する

関連記事

python-onayami.com

日時を表す文字列を日時データに変換したい

Pythonで「日時を表す文字列を日時データに変換する方法」を解説します。

Pythonで文字列を日時データを文字列に変換するには、主に2つの方法があります。

それぞれ見ていきましょう。

1. fromisoformat()メソッドを使う

まずは、ISO 8601書式で表された日時の文字列を日時データに変換する方法です。

ISO 8601書式では、たとえば年-月-日T時:分:秒のように日時を表します(他にもバリエーションがあります)。

このISO 8601書式の文字列を日時データに変換するには、fromisoformat()メソッドが使えます

fromisoformat()datetimeクラスのクラスメソッドで、Python 3.7で追加されました。

このメソッドの使い方は以下の通りです。

datetime.fromisoformat(ISO書式の文字列)

なおfromisoformat()datetimeクラスだけなく、dateクラスとtimeクラスでも使えます。

各クラスの使用例を見ていきましょう。

datetime.fromisoformat()の例

datetimeクラスの場合、たとえば以下のような文字列をdatetimeオブジェクトに変換できます。

>>> from datetime import datetime
>>> # "2022-07-06T12:34:56" を datetime型 に変換
>>> datetime.fromisoformat("2022-07-06T12:34:56")
datetime.datetime(2022, 7, 6, 12, 34, 56)
>>> # "2022-07-06 12:34:56.789" を datetime型 に変換
>>> datetime.fromisoformat("2022-07-06 12:34:56.789")
datetime.datetime(2022, 7, 6, 12, 34, 56, 789000)
>>> # "2022-07-06" を datetime型 に変換
>>> datetime.fromisoformat("2022-07-06")
datetime.datetime(2022, 7, 6, 0, 0)

date.fromisoformat()の例

dateクラスの場合は、年-月-日という書式の文字列をdateオブジェクトに変換できます。

>>> from datetime import date
>>> # "2022-07-06" を date型 に変換
>>> date.fromisoformat("2022-07-06")
datetime.date(2022, 7, 6)

time.fromisoformat()の例

timeクラスの場合は、時:分:秒時:分:秒.マイクロ秒のような時刻の文字列をtimeオブジェクトに変換できます。

>>> from datetime import time
>>> # "12:34:56" を time型 に変換
>>> time.fromisoformat("12:34:56")
datetime.time(12, 34, 56)
>>> # "12:34:56.789" を time型 に変換
>>> time.fromisoformat("12:34:56.789")
datetime.time(12, 34, 56, 789000)
>>> # "12:34:56.778899" を time型 に変換
>>> time.fromisoformat("12:34:56.778899")
datetime.time(12, 34, 56, 778899)

文字列の書式が合わない場合

文字列がISO 8601書式に合わない場合は、ValueErrorが発生します。

>>> datetime.fromisoformat("2022/07/06")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Invalid isoformat string: '2022/07/06'

このように「不正なISO書式の文字列(Invalid isoformat string)」というエラーメッセージが表示されます。

isoformat()との関係

fromisoformat()メソッドはisoformat()メソッドの逆関数(入力と出力が逆になる関数)となっています。

そのため、fromisoformat()メソッドで変換できるのは、isoformat()メソッドで出力される書式の文字列だけです。

ISO 8601書式は上記以外にもいくつか書き方がありますが、それら全ての書き方に対応しているわけではないことに注意しましょう。

isoformat()については、別の記事で解説していますので、末尾の「関連記事」をご参照ください。

2. strptime()メソッドを使う

任意の書式の文字列を日時データに変換したい場合は、datetimeクラスのstrptime()メソッドを使います

このメソッドの使い方は以下の通りです。

datetime.strptime(日時の文字列, 書式)

書式は、以下のように書式化指定子を使って任意の書式を指定できます。

>>> from datetime import datetime
>>> # "年/月/日 時:分:秒" という書式の文字列を変換
>>> datetime.strptime("2022/07/06 12:34:56", "%Y/%m/%d %H:%M:%S")
datetime.datetime(2022, 7, 6, 12, 34, 56)

%Y%mの部分が書式化指定子です。

時刻を含まない場合、以下のようにdatetimeオブジェクトの時刻部分は0になります。

>>> # "年/月/日" という書式の文字列を変換
>>> datetime.strptime("2022/07/06", "%Y/%m/%d")
datetime.datetime(2022, 7, 6, 0, 0)

よく使う書式指定子は以下のようなものがあります。

書式指定子 意味 使用例
%Y 西暦(4桁) 0001, 0002, ..., 2022, 2023, ..., 9998, 9999
%y 西暦(2桁) 00, 01, ..., 99
%m 01, 02, ..., 12
%B 月名 January, February, ..., December
%b 月名(短縮系) Jan, Feb, ..., Dec
%d 日にち 01, 02, ..., 31
%A 曜日名 Sunday, Monday, ..., Saturday
%a 曜日名(短縮系) Sun, Mon, ..., Sat
%H 時(24時間表記) 00, 01, ..., 23
%I 時(12時間表記) 01, 02, ..., 12
%p AM/PM AM, PM
%M 00, 01, ..., 59
%S 00, 01, ..., 59
%f マイクロ秒 000000, 000001, ..., 999999

なお、strptime()datetimeクラスのみに存在し、dateクラスやtimeクラスには存在しません。

文字列の書式が合わない場合

文字列が指定した書式と合わないとVallueErrorが発生します。

>>> datetime.strptime("2022-07-06", "%Y/%m/%d")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/_strptime.py", line 568, in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/_strptime.py", line 349, in _strptime
    raise ValueError("time data %r does not match format %r" %
ValueError: time data '2022-07-06' does not match format '%Y/%m/%d'

このように「書式が合ってない(does not match format)」というエラーメッセージが表示されます。

メソッド名の覚え方:strptime()pとは

strptime()と似た名前のメソッドに、strftime()があります。

私はこの2つをなかなか区別できなったのですが、pfの意味が分かったら簡単に覚えられました。

strptime()pparsepです。

「パース(parse)」は「解析する」という意味なので、strptime()は文字列を解析(parse)して、日時データに変換するメソッドと覚えましょう。

strftime()については、別の記事で解説していますので、末尾の「関連記事」をご参照ください。

3. まとめ

  • ISO 8601書式の文字列を日時データに変換には、fromisoformat()メソッドが使える
    • 対応クラス:datetime date time
  • 任意の書式の文字列を日時データに変換する場合は、datetimeクラスのstrptime()メソッドを使う

関連記事

isoformat()strftime()については、こちらの記事で解説しています。

python-onayami.com

参考情報

日時データを文字列に変換したい

Pythonで日時データを文字列に変換する方法を解説します。

Pythonで日時データを文字列に変換するには、主に2つの方法があります。

それぞれ見ていきましょう。

1. isoformat()メソッドを使う

1つめはisoformat()メソッドを使う方法です。

これは年-月-日T時:分:秒.マイクロ秒のような書式で日時を表現します。

例として、datetimenow()メソッドで取得した現在日時(datetime型のオブジェクト)を、isoformat()メソッドで変換してみましょう。

>>> from datetime import datetime
>>> # 現在日時を取得
>>> dt = datetime.now()
>>> dt
datetime.datetime(2022, 7, 4, 20, 24, 54, 746371)
>>> # isoformat()で文字列に変換
>>> dt.isoformat()
'2022-07-04T20:24:54.746371'

日時データ(dt)が、年-月-日T時:分:秒.マイクロ秒という書式の文字列になったことを確認できました。

なお、マイクロ秒が0であれば、年-月-日T時:分:秒になります。

>>> # マイクロ秒が「0」の日時データを作成
>>> dt = datetime(2022, 7, 4, 12, 34, 56)
>>> dt
datetime.datetime(2022, 7, 4, 12, 34, 56)
>>> # isoformat()で文字列に変換
>>> dt.isoformat()
'2022-07-04T12:34:56'

また、isoformat()メソッドはdatetime型のオブジェクトだけでなく、date型やtime型のオブジェクトでも使えます。

date型のオブジェクトでisoformat()を使用した場合、以下のように年-月-日となります。

>>> from datetime import date
>>> td = date.today()
>>> td
datetime.date(2022, 7, 4)
>>> td.isoformat()
'2022-07-04'

time型のオブジェクトでisoformat()を使用した場合、以下のように時-分-秒となります(マイクロ秒が含まれる場合は時:分:秒.マイクロ秒)。

>>> from datetime import time
>>> t = time(12, 34, 56)
>>> t.isoformat()
'12:34:56'

なお、この書式は日付と時刻の表記に関する国際規格であるISO 8601に従っています。

日時をISO書式で表したい場合は、isoformat()メソッドを使うとよいでしょう。

2. strftime()メソッドを使う

2つめはstrftime()メソッドを使う方法です。

こちらは書式指定子を使い、自分で日時の書式を指定できます

たとえば、年/月/日 時:分:秒という書式の文字列に変換したい場合、以下のようにします。

>>> dt = datetime(2022, 7, 4, 12, 34, 56)
>>> # 「年/月/日 時:分:秒」という書式にする
>>> dt.strftime("%Y/%m/%d %H:%M:%S")
'2022/07/04 12:34:56'

%Y%mなどが書式指定子です。

よく使う書式指定子は以下のようなものがあります。

書式指定子 意味 使用例
%Y 西暦(4桁) 0001, 0002, ..., 2022, 2023, ..., 9998, 9999
%y 西暦(2桁) 00, 01, ..., 99
%m 01, 02, ..., 12
%B 月名 January, February, ..., December
%b 月名(短縮系) Jan, Feb, ..., Dec
%d 日にち 01, 02, ..., 31
%A 曜日名 Sunday, Monday, ..., Saturday
%a 曜日名(短縮系) Sun, Mon, ..., Sat
%H 時(24時間表記) 00, 01, ..., 23
%I 時(12時間表記) 01, 02, ..., 12
%p AM/PM AM, PM
%M 00, 01, ..., 59
%S 00, 01, ..., 59
%f マイクロ秒 000000, 000001, ..., 999999

なお、strftime()メソッドはdate型やtime型のオブジェクトでも使えます。

日時を表す書式を自分で指定したい場合は、strftime()メソッドを使うとよいでしょう。

メソッド名の覚え方:strftime()fとは

strftime()と似た名前のメソッドに、strptime()があります。

私はこの2つをなかなか区別できなったのですが、fpの意味が分かったら簡単に覚えられました。

strftime()fformatfです。

「フォーマット(format)」は「書式」ということなので、strftime()は日時データを指定した書式(format)で表すメソッドと覚えましょう。

strptime()については別の記事で解説予定です。

3. まとめ

  1. 日時データを文字列に変換するには、isoformat()strftime()を使う
    • 日時データ:datetime型、date型、time型のオブジェクト
  2. 日時をISO書式で表したい場合は、isoformat()メソッドを使う
    • ISO書式:年-月-日T時:分:秒.マイクロ秒など
  3. 日時を表す書式を自分で指定したい場合は、strftime()メソッドを使う

参考情報

【エラー解説】KeyErrorとは?原因と対応方法

今回はPythonKeyErrorについて解説します。

1. KeyErrorとは

KeyErrorPythonの組み込み例外の1つで、 「存在しないキーが指定された」 というエラーです。

このエラーは、主に辞書を使った場合に発生します。

簡単に辞書についておさらいしましょう。

以下のように、辞書の要素は「キーのペア」です。

>>> book = {"title": "沈黙の春", "author": "レイチェル カーソン"}

辞書の要素にはキーを使ってアクセスします。

>>> book["title"]
'沈黙の春'
>>> book["author"]
'レイチェル カーソン'

しかし、このキーの指定を間違えるとKeyErrorが発生します。

2. KeyErrorが発生するケース

では、実際にKeyErrorが発生するコード例をみてみましょう。

>>> book["price"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'price'

こちらは存在しないキー"price"を指定しています。

このように存在しないキーを指定すると、KeyErrorが発生します。

もう1つ例を見てみましょう。

>>> book["authar"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'authar'

こちらは存在するキー"author"を指定したつもりでしたが、よく見るとスペルミスで"authar"となっています。

このように、入力ミスでキーの指定を間違え、KeyErrorが発生する場合もあります。

3. KeyErrorの対応方法

KeyErrorの原因は、存在しないキーを指定したことです。

そのため、KeyErrorが発生したら、正しいキーを指定しているかを確認しましょう。

一見、正しいキーを指定しているように見えても、入力ミスで「1文字だけ違う」ということもあるので気をつけましょう。

4. まとめ

  • KeyErrorは存在しないキーを指定した場合に起きるエラー
  • KeyErrorが発生したら、キーの指定が正しいかを確認する