【ヒント】Python引数解析器 ― 悪習

By khoanc, at: 2024年10月18日11:28

Estimated Reading Time: __READING_TIME__ minutes

[TIPS] Python Argument Parser - Bad Practices
[TIPS] Python Argument Parser - Bad Practices

1. sys.argvの直接使用

 

import sys

def main():
    if len(sys.argv) < 3:
        print("引数が足りません!")
        return
    
    arg1 = sys.argv[1]
    arg2 = sys.argv[2]
    
    if arg1 == 'option1':
        print(f"Option 1を選択しました。値は{arg2}です")
    elif arg1 == 'option2':
        print(f"Option 2を選択しました。値は{arg2}です")
    else:
        print("不明なオプションです!")

if __name__ == "__main__":
    main()


悪い例: sys.argvを直接使用して引数を解析すると、エラーが発生しやすく、保守が困難になります。

 

修正: 引数を解析するにはargparseモジュールを使用します。これは、コマンドライン引数を処理するためのより堅牢でユーザーフレンドリーな方法を提供します。

 

import argparse

def main():
    parser = argparse.ArgumentParser(description="引数パーサーのサンプルです。")
    parser.add_argument('arg1', type=str, help="最初の引数")
    parser.add_argument('arg2', type=str, help="2番目の引数")
    args = parser.parse_args()
    
    if args.arg1 == 'option1':
        print(f"Option 1を選択しました。値は{args.arg2}です")
    elif args.arg1 == 'option2':
        print(f"Option 2を選択しました。値は{args.arg2}です")
    else:
        print("不明なオプションです!")

if __name__ == "__main__":
    main()

 

2. 使用方法またはヘルプメッセージがない

 

import sys

def main():
    if len(sys.argv) < 3:
        print("引数が足りません!")
        return
    
    arg1 = sys.argv[1]
    arg2 = sys.argv[2]
    
    if arg1 == 'option1':
        print(f"Option 1を選択しました。値は{arg2}です")
    elif arg1 == 'option2':
        print(f"Option 2を選択しました。値は{arg2}です")
    else:
        print("不明なオプションです!")

if __name__ == "__main__":
    main()


悪い例: 使用方法またはヘルプメッセージを提供しないと、ユーザーがスクリプトの使い方を理解することが困難になります。

修正: argparseモジュールを使用すると、ヘルプメッセージと使用方法が自動的に提供されます。

import argparse

def main():
    parser = argparse.ArgumentParser(description="引数パーサーのサンプルです。")
    parser.add_argument('arg1', type=str, help="最初の引数")
    parser.add_argument('arg2', type=str, help="2番目の引数")
    args = parser.parse_args()
    
    if args.arg1 == 'option1':
        print(f"Option 1を選択しました。値は{args.arg2}です")
    elif args.arg1 == 'option2':
        print(f"Option 2を選択しました。値は{args.arg2}です")
    else:
        print("不明なオプションです!")

if __name__ == "__main__":
    main()

 

引数の検証がない

 

import sys

def main():
    if len(sys.argv) < 3:
        print("引数が足りません!")
        return
    
    arg1 = sys.argv[1]
    arg2 = sys.argv[2]
    
    if arg1 == 'option1':
        print(f"Option 1を選択しました。値は{arg2}です")
    elif arg1 == 'option2':
        print(f"Option 2を選択しました。値は{arg2}です")
    else:
        print("不明なオプションです!")

if __name__ == "__main__":
    main()


悪い例: 引数を検証しないと、ランタイムエラーや予期しない動作が発生する可能性があります。

修正: argparseを使用して、引数の型を指定し、それに応じて検証します。

import argparse

def main():
    parser = argparse.ArgumentParser(description="引数パーサーのサンプルです。")
    parser.add_argument('arg1', type=str, choices=['option1', 'option2'], help="最初の引数")
    parser.add_argument('arg2', type=str, help="2番目の引数")
    args = parser.parse_args()
    
    if args.arg1 == 'option1':
        print(f"Option 1を選択しました。値は{args.arg2}です")
    elif args.arg1 == 'option2':
        print(f"Option 2を選択しました。値は{args.arg2}です")

if __name__ == "__main__":
    main()

 

エッジケースの無視

 

import sys

def main():
    if len(sys.argv) < 3:
        print("引数が足りません!")
        return
    
    arg1 = sys.argv[1]
    arg2 = sys.argv[2]
    
    if arg1 == 'option1':
        print(f"Option 1を選択しました。値は{arg2}です")
    elif arg1 == 'option2':
        print(f"Option 2を選択しました。値は{arg2}です")
    else:
        print("不明なオプションです!")

if __name__ == "__main__":
    main()


悪い例: 引数の不足、データ型の誤り、無効な値などのエッジケースを処理しません。

修正: argparseのデフォルト値、型チェック、必須引数などの機能を使用して、エッジケースを処理します。

import argparse

def main():
    parser = argparse.ArgumentParser(description="引数パーサーのサンプルです。")
    parser.add_argument('arg1', type=str, choices=['option1', 'option2'], help="最初の引数")
    parser.add_argument('arg2', type=str, help="2番目の引数")
    parser.add_argument('--optional', type=int, default=0, help="オプション引数")
    args = parser.parse_args()
    
    if args.arg1 == 'option1':
        print(f"Option 1を選択しました。値は{args.arg2}、オプションは{args.optional}です")
    elif args.arg1 == 'option2':
        print(f"Option 2を選択しました。値は{args.arg2}、オプションは{args.optional}です")

if __name__ == "__main__":
    main()

 

引数の命名が不適切

 

import sys

def main():
    if len(sys.argv) < 3:
        print("引数が足りません!")
        return
    
    arg1 = sys.argv[1]
    arg2 = sys.argv[2]
    
    if arg1 == 'option1':
        print(f"Option 1を選択しました。値は{arg2}です")
    elif arg1 == 'option2':
        print(f"Option 2を選択しました。値は{arg2}です")
    else:
        print("不明なオプションです!")

if __name__ == "__main__":
    main()


悪い例: 説明が不足している、または曖昧な引数名を使用すると、ユーザーを混乱させる可能性があります。

修正: 目的を伝える明確で分かりやすい引数名を使用します。

import argparse

def main():
    parser = argparse.ArgumentParser(description="引数パーサーのサンプルです。")
    parser.add_argument('command', type=str, choices=['start', 'stop'], help="実行するコマンド")
    parser.add_argument('value', type=str, help="コマンドに関連付けられた値")
    args = parser.parse_args()
    
    if args.command == 'start':
        print(f"値{args.value}で開始します")
    elif args.command == 'stop':
        print(f"値{args.value}で停止します")

if __name__ == "__main__":
    main()

 

Tag list:
- args
- Tips
- Tips and Tricks
- parse args python
- args parsers python
- args parsers
- args parse problem
- Args parsers issues
- Argument passing bad practices

Subscribe

Subscribe to our newsletter and never miss out lastest news.