2

ファイル(たとえばparser.py)に次のものがあります:

import argparse

def parse_cmdline(cmdline=None):
    parser = argparse.ArgumentParser()
    parser.add_argument('--first-param',help="Does foo.")
    parser.add_argument('--second-param',help="Does bar.")

    if cmdline is not None:
        args = parser.parse_args(cmdline)
    else:
        args = parser.parse_args()

    return vars(args)

if __name__=='__main__':
    print parse_cmdline()

案の定、コマンド ラインから呼び出すと機能し、期待どおりの結果が得られます。

$ ./parser.py --first-param 123 --second-param 456
{'first_param': '123', 'second_param': '456'}

しかし、私はそれをしたいunittestので、ファイルを書きtest_parser.pyます:

import unittest
from parser import parse_cmdline

class TestParser(unittest.TestCase):
    def test_parse_cmdline(self):
        parsed = parse_cmdline("--first-param 123 --second-param 456")

        self.assertEqual(parsed['first_param'],'123')
        self.assertEqual(parsed['second_param'],'456')

if __name__ == '__main__':
    unittest.main()

次に、次のエラーが表示されます。

usage: test_parser.py [-h] [--first-param FIRST_PARAM]
                      [--second-param SECOND_PARAM]
test_parser.py: error: unrecognized arguments: - - f i r s t - p a r a m   1 2 3   - - s e c o n d - p a r a m   4 5 6
E
======================================================================
ERROR: test_parse_cmdline (__main__.TestParser)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./test_parser.py", line 8, in test_parse_cmdline
    parsed = parse_cmdline("--first-param 123 --second-param 456")
  File "/home/renan/test_argparse/parser.py", line 12, in parse_cmdline
    args = parser.parse_args(cmdline)
  File "/usr/lib/python2.7/argparse.py", line 1691, in parse_args
    self.error(msg % ' '.join(argv))
  File "/usr/lib/python2.7/argparse.py", line 2361, in error
    self.exit(2, _('%s: error: %s\n') % (self.prog, message))
  File "/usr/lib/python2.7/argparse.py", line 2349, in exit
    _sys.exit(status)
SystemExit: 2

----------------------------------------------------------------------
Ran 1 test in 0.004s

FAILED (errors=1)

ご覧のとおり、指定したコマンド ライン ( --first-param 123 --second-param 456) は - - f i r s t - p a r a m 1 2 3 - - s e c o n d - p a r a m 4 5 6(各文字はスペースで区切られています) になりました。

理由がわかりません: 何が間違っているのでしょうか?

4

2 に答える 2

8

argparse「コマンドライン」文字列ではなく、「引数ベクトル」、つまり個別の引数のリストが必要です。

また、電話splitするだけでは解決しません。たとえば、シェルからの次のコマンド ライン:

python script.py --first-param '123 456' --second-param 789

… と が正しく表示されますが123 456789このコード行は次のとおりです。

parse_cmdline("--first-param '123 456' --second-param 789")

しない; それはあなたに'123andを与え、対処方法がわからない789余分なものがあります。456'

実際、これでさえ間違っています。

parse_cmdline("--first-param '123' --second-param 789")

'123'…の代わりに取得するためです123


これに対処するには 2 つの方法があります。

まず、何を渡そうとしているかがわかっている場合は、最初から文字列ではなくリストとして渡すだけでよく、面倒な引用や詳細の分割について心配する必要はありません。

parse_cmdline(["--first-param", "123 456", "--second-param", "789"])

または、何を渡そうとしているか正確にわからない場合は、シェルでどのように見えるかを知っているだけで、次を使用できますshlex

if cmdline is not None:
    args = parser.parse_args(shlex.split(cmdline))

…そして、Python は標準の Unix シェルと同じようにコマンド ラインを分割123 456し、単一のパラメーターとして を取得します。

于 2013-08-20T01:08:39.123 に答える
1

自分自身に答えるには(数分後に間違いに気づきました):

私がすることになっています

if cmdline is not None:
    args = parser.parse_args(cmdline.split())
else:
    args = parser.parse_args()

これで、テストは正しくパスします!

于 2013-08-20T00:41:50.397 に答える