2015-05-02 94 views
1

我對這個模塊非常陌生,所以請耐心等待。我有以下代碼:使用argparse中的子命令創建解析器,自定義位置參數

reader.py

import argparse 

parent_parser = argparse.ArgumentParser(description="Read text files.") 
parent_parser.add_argument('filename', help='TXT file', type=file, nargs='+') 
parent_parser.add_argument('--verbose', '-v', action='store_true', 
     help="Verbosity on") 

child_parser = parent_parser.add_subparsers(title="subcommand", 
     help="Subcommand help") 
new_file_command = child_parser.add_parser('new', help="New text file") 
edit_file_command = child_parser.add_parser('edit', help="Edit existing text file") 

args = parent_parser.parse_args() 

我試圖實現可能並不是解析器和UNIX命令行實用程序是如何工作的標準方式。如果這是真的,請糾正我,因爲我想要有標準化的應用程序。

這就是我想要實現:

  • 如果您運行位置參數(一個或多個)這樣的裸腳本:python reader.py some.txt我想能夠只是解析它,並把它傳遞給函數讀取文本文件,當然我想,如果你運行的子命令接受可選ARG verbose以及
  • 「新」(new_file_command),我不希望有位置參數filename被需要,而不是我想通過一個字符串並創建如下新文本文件:python reader.py new another.txt
  • 如果您運行的子命令「編輯」(edit_file_command),我想通過現有的文件路徑,並檢查它(就像你在add_argument使用type=int),然後也許它傳遞的功能,打開編輯器,像這樣:python reader.py edit some.txt

同樣,我不確定這是命令行應用程序/腳本應該如何表現。我閱讀了文檔並查看了示例,但對於我來說,還不清楚子解析器是如何工作的。我試着看看Click模塊,但在我看來,這更復雜。

任何幫助表示讚賞。謝謝!

回答

2

所以三個示例電話是:

python reader.py some.txt 
python reader.py new another.txt 
python reader.py edit some.txt 

處理這些最簡單的方法是用一個「可選」位置,以及一個要求之一。

parser = ArgumentParser... 
parser.add_argument('-v','--verbose', ...) 
parser.add_argument('cmd', nargs='?', default='open', choices=['open','edit','new']) 
parser.add_argument('filename') 

爲您3個樣本,它應該產生這樣的:

namespace(cmd='open', filename='some.txt') 
namespace(cmd='new', filename='another.txt') 
namespace(cmd='edit', filename='some.txt') 

cmd是一個可選的位置參數。如果缺失,則將一個字符串分配給filename,並且cmd得到其default。比嘗試使subparsers可選更容易。


至於當前的解析器:

parent_parser = argparse.ArgumentParser(description="Read text files.") 
parent_parser.add_argument('filename', help='TXT file', type=file, nargs='+') 

我不建議使用type=file。最好使用FileType或默認字符串(可讓您稍後在with context中打開文件)。

至於nargs='+',你真的想分配1 or more字符串到filename?或者你是在想'?',那會是0 or 1,也就是說它是可選的?

parent_parser.add_argument('--verbose', '-v', action='store_true', 
     help="Verbosity on") 

child_parser = parent_parser.add_subparsers(title="subcommand", 
     help="Subcommand help") 
new_file_command = child_parser.add_parser('new', help="New text file") 
edit_file_command = child_parser.add_parser('edit', help="Edit existing text file") 

混合此filename位置,其接受可變數量的值,與subparsers參數(即期望要麼newedit的位置)可能是一個問題。

我希望​​反對subparser命令丟失。 'python reader.py new another.txt'會嘗試將new分配給filenameanother.txt以分包器,並引發錯誤。

倒不如在所有3個案件期望subparsers命令:

parent_parser = argparse.ArgumentParser(description="Read text files.") 
parent_parser.add_argument('--verbose', '-v', action='store_true', 
     help="Verbosity on") 
child_parser = parent_parser.add_subparsers(title="subcommand", 
     help="Subcommand help", dest='cmd') 
open_file_command = child_parser.add_parser('open', help="Open text file") 
open_file_command.add_argument('filename', help='TXT file') 
new_file_command = child_parser.add_parser('new', help="New text file") 
new_file_command.add_argument('filename', help='TXT file') 
edit_file_command = child_parser.add_parser('edit', help="Edit existing text file") 
edit_file_command.add_argument('filename', help='TXT file') 

每一個命令,「開放」,「新」,「編輯」,需要一個「文件名」。

試圖避免使用open命令將產生比它的價值更多的困難。

(存在這樣使得subparsers可選最新argparse一個bug /功能,但你不應該利用這一點沒有真正知道的問題。)


有了:

parser = argparse.ArgumentParser() 
parser.add_argument('-v', '--verbose') 
parser.add_argument('cmd', nargs='?', default='open', 
    choices=['open', 'edit', 'new']) 
parser.add_argument('filename', nargs='+') 

我希望reader.py new customstring

namespace(cmd='new', filename=[customstring]) 

它可以用作:

if args.cmd=='new': 
with open(args.filename[0] + '.txt', 'w') as f: 
    # do something with the newly created file 

openedit會使用不同的open模式。

+0

嗨,感謝您的幫助。我還有最後一個問題。我仍然想知道如何定製位置參數。假設我有以下代碼: parser = argparse.ArgumentParser() parser.add_argument(' - v','--verbose') parser.add_argument('cmd',nargs ='?',default ='open ',options = ['open','edit','new']) parser.add_argument('filename',nargs ='+') 如果我想自定義命令'new'的位置參數?我不需要/希望傳遞明確的文件名,而只需要一個像'some'這樣的字符串,然後創建文件'some.txt'。我該怎麼做呢?謝謝 – user3056783

+0

你可以創建一個自定義的'type'或'Action'。但通常在解析後進行這種更改會更簡單。特別是如果你沒有對「某些」進行錯誤檢查。 – hpaulj

+0

嗨我還在閱讀文檔,並試圖找出這一點,但我無法在網上找到更多的例子。你能告訴我一個片段,你將如何實現這個解析後?因爲如果我執行'reader.py new customstring',它會對現有文件名進行錯誤檢查,所以它不會讓我做任何事情。 – user3056783