【ヒント】Python引数解析器 ― 悪習
By khoanc, at: 2024年10月18日11:28
Estimated Reading Time: __READING_TIME__ minutes
![[TIPS] Python Argument Parser - Bad Practices](/media/filer_public_thumbnails/filer_public/53/22/532205b4-0a89-4637-9f86-e7d316454d2b/python_argument_parsers_issues.png__1500x900_crop_subsampling-2_upscale.png)
![[TIPS] Python Argument Parser - Bad Practices](/media/filer_public_thumbnails/filer_public/53/22/532205b4-0a89-4637-9f86-e7d316454d2b/python_argument_parsers_issues.png__400x240_crop_subsampling-2_upscale.png)
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()