結論
pythonのモジュールを上書きしてしまうとエラーが発生することがあります。
思わぬところで上書きしてしまうことがありそうなので注意が必要です。
実際に起きたエラーを再現
以下のように、for文の変数名に「time」を使用した後、別の関数でtime.sleep関数を使用したところ、エラーが発生しました。
import time
def test():
time.sleep(1)# エラー発生
if __name__ == '__main__':
times = ['2:50', '3:00', '3:10']
# for文の変数名に「time」を使用している
for time in times:
print(time)
test()
print('OK')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-7dc118a6741a> in <cell line: 6>()
8 for time in times:
9 print(time)
---> 10 test()
11 print('OK')
<ipython-input-8-7dc118a6741a> in test()
2
3 def test():
----> 4 time.sleep(1)
5
6 if __name__ == '__main__':
AttributeError: 'str' object has no attribute 'sleep'
調査
以下の記事を参考にしました。
どうやら、for文の変数名に「time」を使用したことによって、importしたtimeモジュールが上書きされたことで意図しないエラーが発生したようでした。
調査を踏まえての対策
for文の変数名を変更しました。
import time
def test():
time.sleep(1)
if __name__ == '__main__':
time_schedules = ['2:50', '3:00', '3:10']
# for文の変数名に「time_schedule」を使用
for time_schedule in time_schedules:
print(time_schedule)
test()
print('OK')
これでエラーが発生しなくなりました。
あとがき
特にtimeモジュールは「time」がよく使う単語なので注意が必要かもと思いました。
私は詳しくないですがどうやらpythonは変数のスコープが複雑そうなので、それに起因した思わぬエラーが出てくることもあるかもと思いました。
そのあたりについては他の方の記事を調べてみると勉強になるかもしれないです!
追記
@shiracamusさんにコメントで教えていただきました。ありがとうございます!
mainの処理を関数化することでfor文で使用していた「time」がローカル変数となり、今回の問題のエラー発生を防ぐことができます。
import time
def test():
time.sleep(1)
# mainを関数化
def main():
times = ['2:50', '3:00', '3:10']
# ここのtimeはローカル変数になる
for time in times:
print(time)
test()
print('OK')
if __name__ == '__main__':
main()
確かに、よく考えると「if __name__ == '__main__':
」ではまだ関数化できていないですね。
勉強になりました!