argparseのサブコマンドからのdispatchと引数の一致¶
問題点¶
- クラスへ割り当て各メソッドをサブコマンドとする場合、サブコマンド間で異なる引数をInit時にむりくりContextとする
- ContextObjectを作って各関数に割り当てても同じ
- どちらの場合もメソッド・関数の引数がないに等しい
- ただし、クラスなら一応他でも使える
というのを考えた時、関数から地道に各サブコマンドに対応するContextを処理して、それぞれのクラスにしたほうがよさそう?Airflowがそうしていた
コード¶
arg_context.py
import argparse
class MyClass:
def __init__(self, year, month):
self.year = year
self.month = month
def fun():
# do something
class Context:
def __init__(self, args):
self.year = args.year
self.month = args.month
def func1_for_sub(args):
context = Context(args)
# do something
if __name__ == '__main__':
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
parser.add_argument('-y', '--year', required=True, type=int)
parser.add_argument('-m', '--month', required=True, type=int)
subcommand_parser = subparsers.add_parser('subcommand')
subcommand_parser.set_defaults(func=MyClass.fun)
args = parser.parse_args()
funcname = args.func.__name__
del args.func
c = MyClass(**vars(args))
getattr(c, funcname)()
args_to_dict.py
import argparse
if __name__ == "__main__":
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
parser.add_argument('-y', '--year', required=True, type=int)
parser.add_argument('-m', '--month', required=True, type=int)
parser.add_argument('-d', '--day', required=True, type=int)
mytest_parser = subparsers.add_parser('mytest')
def mytest(year, month, day):
print(locals())
mytest_parser.set_defaults(func=mytest)
args = parser.parse_args()
print(args) # namespace object
dict_args = vars(args)
#args.func(**dict_args) # TypeError: mytest() got an unexpected keyword argument 'func'