2015-11-02 81 views
2

嗨,大家好,我是編程和Python新手。我尋找我的問題的答案,但我無法找到它。如何在Python中跳過位置參數Argparse

我使用Argparse爲我的腳本解析參數。現在我想編寫一個運行特定工具的程序,如果第一個參數(程序名稱後面)是工具的名稱(在類中關閉)。例如,如果我想運行「計數器」工具,我必須鍵入:

python myscript.py counter filename 

而如果我想運行「fasta2bed」我必須鍵入:

python myscript.py fasta2bed filename 

我寫了這個代碼,但好像你不能跳過的位置參數與Argparse:

import argparse 

parser=argparse.ArgumentParser(
    usage="""python myscript.py {toolname} filename [-option]""", 
    description='''Description.''', 
    epilog="""Epilog.""") 
parser.add_argument('counter', nargs='?', choices=['counter'],  help='count how many features are in the input file [-l][-s]') 
parser.add_argument('fasta2bed', nargs='?', choices=['fasta2bed'], help='read sequences in FASTA format and print out BED format') 
parser.add_argument('filename', help='the input file name') 
parser.add_argument('-l', '--long', action='store_true', help='retrive a long summary file (default)') 
parser.add_argument('-s', '--short', action='store_true', help='retrive a short summary file') 
args=parser.parse_args() 

的問題是,當我嘗試運行python myscript.py fasta2bed文件名這是行不通的,因爲它需要計數器。

所以我嘗試插入所有在這樣一個參數:

parser.add_argument('tool', nargs='?', choices=['counter', 'fasta2bed'], help='help') 

這個目的:

data = open("inputfile", "r") 

if args.tool == "counter": 
    counter(data).summarize()  #summarize is a function present in the counter class 
elif args.tool == "fasta2bed": 
    fasta2bed(data)    #fasta2bed is just a function 

,但因爲它運行fasta2bed的櫃檯,而不是它不工作.. 。

有沒有辦法達到這個目標?也許沒有argparse?

非常感謝您的時間!

+0

沒有你看看docopt(https://github.com/docopt/docopt)更容易使用 – Salo

+1

我認爲這將是非常有用的,非常感謝你! – Revo

回答

2

據我所知,你不能跳過的參數,你似乎想要的方式。這就是說,看來你並不是真的想要跳過一個。做到這一點的方式是改變你看問題的方式。有效的辦法是有一個接受「counter」或「fasta2bed」的單一論點。更改代碼中的相關行可能會產生類似如下內容:

import argparse 
parser=argparse.ArgumentParser(
    usage="""python myscript.py {toolname} filename [-option]""", 
    description='''Description.''', 
    epilog="""Epilog.""") 
parser.add_argument('toolname', choices=['counter', 'fasta2bed'], help='the name of the tool to be used') 
parser.add_argument('filename', help='the input file name') 
parser.add_argument('-l', '--long', action='store_true',  help='retrive a long summary file (default)') 
parser.add_argument('-s', '--short', action='store_true', help='retrive a short summary file') 
args=parser.parse_args() 

希望這能幫助您入門。

編輯用於添加材料:

您可以檢查通過檢查args.toolname爲工具名的選擇:

if args.toolname == 'counter': 
    print 'Running counter' 
else: 
    print 'Running fasta2bed' 

請注意,您需要使用elif,如果你有2個以上選擇。

+0

@chepner - 啊,是的,複製和粘貼得太快了......現在修復了,謝謝! – GreenMatt

+0

非常感謝!兩個不同的功能,以對抗fasta2bed?我試着用if語句,但它沒有工作,並且總是運行計數器而不是fastabed :( – Revo

+0

@Revo:你在正確的過程中,請檢查我添加到我的答案。 – GreenMatt

0

難道工作中使用類似:

parser.add_argument('--counter', action='store_true', default=False) 
parser.add_argument('--fasta2bed', action='store_true', default=False) 

而且在Python腳本後,檢查直接的參數,你可以使用:

import sys 

filename, methodname = sys.argv 

現在你必須傳遞給第一個參數你腳本分成methodname

+0

但在第二種方式,可我得到像argparse一個一個幫助頁面?非常感謝你! – Revo

2

用您的腳本複製一行

parser.add_argument('tool', choices=['counter', 'fasta2bed'], help='help') 

print(args) 

我獲得所需的行爲

0827:~/mypy$ python stack33480471.py counter filename 
Namespace(filename='filename', long=False, short=False, tool='counter') 
0828:~/mypy$ python stack33480471.py fasta2bed filename 
Namespace(filename='filename', long=False, short=False, tool='fasta2bed') 
0828:~/mypy$ python stack33480471.py tool filename 
usage: python myscript.py {toolname} filename [-option] 
stack33480471.py: error: argument tool: invalid choice: 'tool' (choose from 'counter', 'fasta2bed') 

注意,我放棄了nargs='?'。解析更清晰,更具可預測性。我只是顯示args。在丟失測試特定值之前,您需要清楚知道產生的命名空間是什麼樣的。如果用戶不提供選擇會發生什麼?

別人可能會建議使用子分析器。我認爲這是一個先進的工具,往往會造成更多的困惑。

使用store_true optionals也是一個好主意。但它需要使用'--counter'而不是'counter'。這並不差,只是不同。

+0

非常感謝!我如何分配兩個不同的函數來對抗fasta2bed?我嘗試了一個if語句,但它沒有工作,並且總是運行計數器:( – Revo