Skip to content

Instantly share code, notes, and snippets.

@yusukemurayama
Created May 18, 2016 02:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yusukemurayama/734bf431b596d478f66c408d7dbea276 to your computer and use it in GitHub Desktop.
Save yusukemurayama/734bf431b596d478f66c408d7dbea276 to your computer and use it in GitHub Desktop.
# coding: utf-8
import sys
import argparse
def sample1():
"""
ハイフンがある引数を取る場合
引数の例)
--mode 1 --verbose
--m 2
"""
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--mode', type=int, required=True)
parser.add_argument('-v', '--verbose', action='store_true')
args = parser.parse_args()
return args
def sample2():
"""
ハイフンがない引数を取る場合
引数の例)
a b c
"""
parser = argparse.ArgumentParser()
parser.add_argument('strings', type=str, nargs='+', metavar='STR') # 引数を1個以上取ります。
args = parser.parse_args()
return args
def sample3(strings):
"""
parser.parse_argsの引数を、デフォルトのsys.argv[1:]から変更しています。
"""
parser = argparse.ArgumentParser()
parser.add_argument('strings', type=str, nargs='*', metavar='STR') # 引数を0個以上取ります。
args = parser.parse_args(strings)
return args
def sample4():
"""
ハイフンあり、なしが混合している場合
ハイフンがない引数の、1つ目をコマンド名とします。
引数の例)
update_data foo bar -v -m 1
-v update_data foo bar -m 1
以下のように、コマンド名の後にハイフン付き引数があり、
それからハイフンなし引数があると例外が発生します。
-v update_data -m 1 foo bar
"""
parser = argparse.ArgumentParser()
parser.add_argument('command', type=str, nargs=1)
parser.add_argument('-v', '--verbose', action='store_true')
parser.add_argument('-m', '--mode', type=int, required=True)
parser.add_argument('strings', type=str, nargs='*', metavar='STR')
args = parser.parse_args()
return args
def sample5():
"""
ハイフンあり、なしが混合している場合
ハイフンがない引数の、1つめをコマンド名とします。
コマンド名の後にハイフン付き引数があり、その後にハイフン無し引数があってもエラーは発生しません。
引数の例)
update_data foo bar -v -m 1
-v update_data foo bar -m 1
-v update_data -m 1 foo bar
"""
command, new_args = None, []
parser = argparse.ArgumentParser()
parser.add_argument('command', type=str, nargs=1)
# parse_known_argsを使い、未知の引数があってもエラーとならないようにします。
for args in parser.parse_known_args():
if hasattr(args, 'command'): # commandの場合は変数に格納しておきます。
command = args.command[0]
continue
new_args.extend(args) # command以外の引数を配列に入れておきます。
# キーワード引数progを指定して、usageにコマンド名を表示するようにします。
# ※ parse_argsで指定するnew_argsにはコマンド名がないので、
# 指定しないとusageでコマンド名が表示されません。
parser = argparse.ArgumentParser(prog='{} {}'.format(sys.argv[0], command))
parser.add_argument('-v', '--verbose', action='store_true')
parser.add_argument('-m', '--mode', type=int, required=True)
parser.add_argument('strings', type=str, nargs='*', metavar='STR')
args = parser.parse_args(new_args) # コマンド名を覗いた配列を解析します。
return command, args
# coding: utf-8
import unittest
import sys
import argparse_samples
class TestArgparse(unittest.TestCase):
def setUp(self):
super().setUp()
sys.argv = [argparse_samples.__name__]
def test11(self):
sys.argv.extend(['--mode=1', '--verbose'])
args = argparse_samples.sample1()
self.assertEqual(args.mode, 1)
self.assertTrue(args.verbose)
def test12(self):
sys.argv.extend(['-m', '2'])
args = argparse_samples.sample1()
self.assertEqual(args.mode, 2)
self.assertFalse(args.verbose)
def test13(self):
sys.argv.extend(['-v'])
# --mode(required)の指定がないので例外が発生します。
self.assertRaises(SystemExit, argparse_samples.sample1)
def test21(self):
sys.argv.extend(['a', 'b', 'c'])
strings = argparse_samples.sample2().strings
self.assertEqual(len(strings), 3)
self.assertEqual(strings[0], 'a')
self.assertEqual(strings[1], 'b')
self.assertEqual(strings[2], 'c')
def test31(self):
strings = argparse_samples.sample3(['A', 'B', 'C', 'D']).strings
self.assertEqual(len(strings), 4)
self.assertEqual(strings[0], 'A')
self.assertEqual(strings[1], 'B')
self.assertEqual(strings[2], 'C')
self.assertEqual(strings[3], 'D')
def test41(self):
sys.argv.extend(['update_data', 'foo', 'bar', '-v', '-m', '1'])
args = argparse_samples.sample4()
self.assertEqual(args.command[0], 'update_data')
self.assertEqual(args.strings[0], 'foo')
self.assertEqual(args.strings[1], 'bar')
self.assertTrue(args.verbose)
self.assertEqual(args.mode, 1)
def test42(self):
sys.argv.extend(['-v', 'update_data', 'foo', 'bar', '-m', '1'])
args = argparse_samples.sample4()
self.assertEqual(args.command[0], 'update_data')
self.assertEqual(args.strings[0], 'foo')
self.assertEqual(args.strings[1], 'bar')
self.assertTrue(args.verbose)
self.assertEqual(args.mode, 1)
def test43(self):
sys.argv.extend(['-v', 'update_data', '-m', '1', 'foo', 'bar'])
self.assertRaises(SystemExit, argparse_samples.sample4)
def test51(self):
sys.argv.extend(['update_data', 'foo', 'bar', '-v', '-m', '1'])
command, args = argparse_samples.sample5()
self.assertEqual(command, 'update_data')
self.assertEqual(args.strings[0], 'foo')
self.assertEqual(args.strings[1], 'bar')
self.assertTrue(args.verbose)
self.assertEqual(args.mode, 1)
def test52(self):
sys.argv.extend(['-v', 'update_data', 'foo', 'bar', '-m', '1'])
command, args = argparse_samples.sample5()
self.assertEqual(command, 'update_data')
self.assertEqual(args.strings[0], 'foo')
self.assertEqual(args.strings[1], 'bar')
self.assertTrue(args.verbose)
self.assertEqual(args.mode, 1)
def test53(self):
sys.argv.extend(['-v', 'update_data', '-m', '1', 'foo', 'bar'])
command, args = argparse_samples.sample5()
self.assertEqual(command, 'update_data')
self.assertEqual(args.strings[0], 'foo')
self.assertEqual(args.strings[1], 'bar')
self.assertTrue(args.verbose)
self.assertEqual(args.mode, 1)
if __name__ == '__main__':
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment