Home Pythonの型アノテーションを自動化する
Post
Cancel

Pythonの型アノテーションを自動化する

概要

  • 型を明示しておくことにより、Doumentを書く時やコードレビューする際にコードを説明する時などに理解しやすくする
  • 理解しやすくなれば、理解するための時間が短縮できる

  • 型アノテーションを自動化し、FormatterやLinterのように使用したい
    • コード量が多くなってくると、アノテーションのための時間も増えてしまう
    • アノテーションには時間をかけず、アルゴリズム/ロジックの方に時間を使いたい

TypeAnnotaion用のコード

  • ROSの公式のサンプルコードを使用する
    • talker.py

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      
        #!/usr/bin/env python
        import rospy
        from std_msgs.msg import String
      
        def talker():
            pub = rospy.Publisher('chatter', String, queue_size=10)
            rospy.init_node('talker', anonymous=True)
            r = rospy.Rate(10) # 10hz
            while not rospy.is_shutdown():
                str = "hello world %s"%rospy.get_time()
                rospy.loginfo(str)
                pub.publish(str)
                r.sleep()
      
        if __name__ == '__main__':
            try:
                talker()
            except rospy.ROSInterruptException: pass
      
    • main.py

      1
      2
      3
      4
      5
      
        #!/usr/bin/env python
        from talker import talker
      
        if __name__ == '__main__':
            talker()
      

自動型アノテーションツール

MonkeyType

  • Instagramが公開している静的型アノテーション生成ライブラリ
  • install MonkeyType
1
pip install MonkyType
  • MonkeyTypeは各モジュールのAnnotation結果をSQLlite形式のデータで出力する

  • 実行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# run でAnotationを実行
$ monkeytype run main.py

# stub でAnotation結果を確認
$ monkeytype stub talker
def talker() -> None: ...

# applyでAnnotation結果を上書き
$ monkeytype apply talker
#!/usr/bin/env python
# license removed for brevity
import rospy
from std_msgs.msg import String

def talker() -> None:
    pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node('talker', anonymous=True)
    r = rospy.Rate(10) # 10hz
    while not rospy.is_shutdown():
        str = "hello world %s"%rospy.get_time()
        rospy.loginfo(str)
        pub.publish(str)
        r.sleep()

型チェックツール

MyPy

  • mypyは型チェックのライブラリ
  • install mypy
1
pip install mypy
  • zshの場合は次の2行を.zshrcに追加する
1
2
export PATH="$PATH:/home/sota/.local/bin"
[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
  • 実行結果
    • 事前にcatkin_wsのsetup.zshを読み込ませたが、rospyを認識できていない
1
2
3
4
5
$ mypy talker.py
talker.py:3: error: Cannot find implementation or library stub for module named "rospy"
talker.py:3: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
talker.py:4: error: Cannot find implementation or library stub for module named "std_msgs.msg"
Found 2 errors in 1 file (checked 1 source file)
  • findに失敗したLibraryを無視するオプション (–ignore-missing-imports)+ all optional error checking flag(–strict)を付けて実行
1
2
3
4
$ mypy --ignore-missing-imports --strict talker.py
talker.py:6: error: Function is missing a return type annotation
talker.py:6: note: Use "-> None" if function does not return a value
Found 1 error in 1 file (checked 1 source file)
  • Functionの返り値の型が無いというエラーがでおり、”-> None” を使えと言われているので、付けて再実行すると、型チェックをパスする
1
2
$ mypy --ignore-missing-imports --strict talker.py
Success: no issues found in 1 source file

Pyannotate

  • DropBoxが公開しているPEP-484準拠の自動型アノテーションライブラリ
  • 最終更新が2年前であるため、使いづらいかも

参考

  • PyannotateとMokeyTypeの比較
    • https://qiita.com/t2y/items/f16a30cb7c4aec8332c2
  • MyPy
    • https://mypy-lang.org/
    • https://mypy.readthedocs.io/en/stable/getting_started.html
  • TypeAnnotation in python
    • https://towardsdatascience.com/type-annotations-in-python-d90990b172dc
  • Type Annotations in attrs
    • https://www.attrs.org/en/stable/types.html
  • UnderStanding type annotation in Python
    • https://blog.logrocket.com/understanding-type-annotation-python/
This post is licensed under CC BY 4.0 by the author.