2010-10-04 121 views
222

我使用argparse in Python 2.7來解析輸入選項。我的一個選擇是多選。我想在其幫助文本中列出一個列表,例如Python argparse:如何在幫助文本中插入換行符?

from argparse import ArgumentParser 

parser = ArgumentParser(description='test') 

parser.add_argument('-g', choices=['a', 'b', 'g', 'd', 'e'], default='a', 
    help="Some option, where\n" 
     " a = alpha\n" 
     " b = beta\n" 
     " g = gamma\n" 
     " d = delta\n" 
     " e = epsilon") 

parser.parse_args() 

但是,​​剝離了所有換行符和連續空格。結果看起來像

 
~/Downloads:52$ python2.7 x.py -h 
usage: x.py [-h] [-g {a,b,g,d,e}] 

test 

optional arguments: 
    -h, --help  show this help message and exit 
    -g {a,b,g,d,e} Some option, where a = alpha b = beta g = gamma d = delta e 
        = epsilon 

如何在幫助文本中插入換行符?

+0

我沒有Python 2.7,所以我可以測試我的想法。如何在三重引號中使用幫助文本(「」「」「」)。新的生產線是否能夠繼續生存下去? – pyfunc 2010-10-04 08:48:01

+3

@pyfunc:不可以。剝離是由'argparse'在運行時完成的,而不是解釋器,因此切換到''「」「...」「」'將無濟於事。 – kennytm 2010-10-04 08:50:04

回答

255

嘗試使用RawTextHelpFormatter

from argparse import RawTextHelpFormatter 
parser = ArgumentParser(description='test', formatter_class=RawTextHelpFormatter) 
+4

不錯,謝謝。是否有可能僅適用於1選項? – kennytm 2010-10-04 08:52:46

+4

我認爲不是。你可以繼承它,但不幸的是 '只有這個類的名字被認爲是一個公共的API。這個類提供的所有方法都被認爲是一個實現細節。「因此,雖然可能並不重要,但可能不是一個好主意,因爲2.7意味着最後一個2.x python,並且你可能會重構很多東西對於3.x無論如何。我實際上運行2.6,通過'easy_install'安裝'argparse',這樣文檔本身可能會過時。 – intuited 2010-10-04 09:00:45

+3

一些鏈接:for [python 2.7](http://docs.python.org/library/argparse.html#formatter-class)和[python 3. *](http://docs.python.org/dev /library/argparse.html#formatter-class)。根據[其wiki](http://code.google.com/p/argparse/),2.6軟件包應符合2.7官方的規定。來自doc:「將RawDescriptionHelpFormatter傳遞爲formatter_class =表示描述和epilog已經被正確格式化並且不應該被行包裝」 – Stefano 2011-11-21 15:34:32

53

如果你只是想重寫一個選項,則不應使用RawTextHelpFormatter。取而代之的子類HelpFormatter,並提供該應處理「原始」的選項特別介紹(我用"R|rest of help"):

import argparse 

class SmartFormatter(argparse.HelpFormatter): 

    def _split_lines(self, text, width): 
     if text.startswith('R|'): 
      return text[2:].splitlines() 
     # this is the RawTextHelpFormatter._split_lines 
     return argparse.HelpFormatter._split_lines(self, text, width) 

並使用它:

from argparse import ArgumentParser 

parser = ArgumentParser(description='test', formatter_class=SmartFormatter) 

parser.add_argument('-g', choices=['a', 'b', 'g', 'd', 'e'], default='a', 
    help="R|Some option, where\n" 
     " a = alpha\n" 
     " b = beta\n" 
     " g = gamma\n" 
     " d = delta\n" 
     " e = epsilon") 

parser.parse_args() 

任何其他調用.add_argument()其中幫助不以R|開始將被正常包裝。

這是my improvements on argparse的一部分。完整的SmartFormatter還支持將缺省值添加到所有選項,以及實用程序描述的原始輸入。完整版 有其自己的_split_lines方法,因此任何格式都可以通過例如版本字符串保留:

parser.add_argument('--version', '-v', action="version", 
        version="version...\n 42!") 
+0

我想爲版本信息做到這一點,但是這個SmartFormatter只能用於幫助文本,而不是特殊版本的文本。 'parser.add_argument(' - v','--version',action ='version',version = get_version_str())' 是否可以將它擴展到這種情況? – 2014-04-02 03:14:12

+0

@mc_electron SmartFormatter的完整版本也有它自己的'_split_lines'並且保留換行符(如果你想要這個選項,不需要在開頭指定「R |」,修補'_VersionAction .__ call__'方法 – Anthon 2014-04-02 11:18:02

+0

'雖然我可以在'_VersionAction .__ call__'中看到我可能希望它只是'parser.exit(message = version)',而不是使用格式化版本,但是它並不完全滿足您的評論的第一部分。要做到這一點,而不發佈補丁副本雖然? – 2014-04-03 20:45:56

7

我遇到過類似的問題(Python 2.7.6)。我試着描述部分分解成使用RawTextHelpFormatter幾行:

parser = ArgumentParser(description="""First paragraph 

             Second paragraph 

             Third paragraph""", 
             usage='%(prog)s [OPTIONS]', 
             formatter_class=RawTextHelpFormatter) 

options = parser.parse_args() 

,並得到:

 
usage: play-with-argparse.py [OPTIONS] 

First paragraph 

         Second paragraph 

         Third paragraph 

optional arguments: 
    -h, --help show this help message and exit 

所以RawTextHelpFormatter是不是一個解決方案。因爲它打印出現在源代碼中的描述,保留所有空白字符(爲了便於閱讀,我想在源代碼中保留額外的標籤,但我不想將它們全部打印出來。太長,例如超過80個字符)。

非常感謝@Anton啓發了正確的方向above。但是該解決方案需要稍作修改才能格式化說明部分。

無論如何,自定義格式化程序是必要的。我擴展現有HelpFormatter類和推翻_fill_text方法是這樣的:

import textwrap as _textwrap 
class MultilineFormatter(argparse.HelpFormatter): 
    def _fill_text(self, text, width, indent): 
     text = self._whitespace_matcher.sub(' ', text).strip() 
     paragraphs = text.split('|n ') 
     multiline_text = '' 
     for paragraph in paragraphs: 
      formatted_paragraph = _textwrap.fill(paragraph, width, initial_indent=indent, subsequent_indent=indent) + '\n\n' 
      multiline_text = multiline_text + formatted_paragraph 
     return multiline_text 

與來自argparse模塊傳來的原始源代碼比較:

def _fill_text(self, text, width, indent): 
    text = self._whitespace_matcher.sub(' ', text).strip() 
    return _textwrap.fill(text, width, initial_indent=indent, 
             subsequent_indent=indent) 

在原始代碼中的整個說明書被包裝。在上面的自定義格式化程序中,整個文本被分成幾個塊,並且每個塊都被獨立格式化。

因此,與自定義格式的援助:

parser = ArgumentParser(description= """First paragraph 
             |n        
             Second paragraph 
             |n 
             Third paragraph""", 
       usage='%(prog)s [OPTIONS]', 
       formatter_class=MultilineFormatter) 

options = parser.parse_args() 

輸出爲:

 
usage: play-with-argparse.py [OPTIONS] 

First paragraph 

Second paragraph 

Third paragraph 

optional arguments: 
    -h, --help show this help message and exit 
+1

這真是太好了 - 在發生這種事情之後,幾乎放棄並考慮完全重新實施幫助論證......爲我省去了很多麻煩。 – 2015-11-30 19:38:08

+2

子類化'HelpFormatter'是有問題的,因爲argparse開發者只保證類名將在未來版本的argparse中生存。他們基本上自己寫了一張空白支票,以便他們可以改變方法名稱,如果方便的話。我發現這令人沮喪;他們至少可以做的就是在API中暴露一些方法。 – MrMas 2016-03-18 16:14:02

20

另一種簡單的方法來做到這一點是包括textwrap

例如,

import argparse, textwrap 
parser = argparse.ArgumentParser(description='some information', 
     usage='use "python %(prog)s --help" for more information', 
     formatter_class=argparse.RawTextHelpFormatter) 

parser.add_argument('--argument', default=somedefault, type=sometype, 
     help= textwrap.dedent('''\ 
     First line 
     Second line 
     More lines ... ''')) 

以這種方式,我們能夠避免在每條輸出線的前方的長空的空間。

usage: use "python your_python_program.py --help" for more information 

Prepare input file 

optional arguments: 
-h, --help   show this help message and exit 
--argument ARGUMENT 
         First line 
         Second line 
         More lines ... 
-1

我希望在說明文字中有兩個手動換行符,並自動換行;但這裏沒有任何建議適用於我 - 所以我最終修改了這裏答案中給出的SmartFormatter類;與非公共API儘管如此,這裏的argparse方法名的問題是我有什麼(如一個名爲test.py):

import argparse 
from argparse import RawDescriptionHelpFormatter 

# call with: python test.py -h 

class SmartDescriptionFormatter(argparse.RawDescriptionHelpFormatter): 
    #def _split_lines(self, text, width): # RawTextHelpFormatter, although function name might change depending on Python 
    def _fill_text(self, text, width, indent): # RawDescriptionHelpFormatter, although function name might change depending on Python 
    #print("splot",text) 
    if text.startswith('R|'): 
     paragraphs = text[2:].splitlines() 
     rebroken = [argparse._textwrap.wrap(tpar, width) for tpar in paragraphs] 
     #print(rebroken) 
     rebrokenstr = [] 
     for tlinearr in rebroken: 
     if (len(tlinearr) == 0): 
      rebrokenstr.append("") 
     else: 
      for tlinepiece in tlinearr: 
      rebrokenstr.append(tlinepiece) 
     #print(rebrokenstr) 
     return '\n'.join(rebrokenstr) #(argparse._textwrap.wrap(text[2:], width)) 
    # this is the RawTextHelpFormatter._split_lines 
    #return argparse.HelpFormatter._split_lines(self, text, width) 
    return argparse.RawDescriptionHelpFormatter._fill_text(self, text, width, indent) 

parser = argparse.ArgumentParser(formatter_class=SmartDescriptionFormatter, description="""R|Blahbla bla blah blahh/blahbla (bla blah-blabla) a blahblah bl a blaha-blah .blah blah 

Blah blah bla blahblah, bla blahblah blah blah bl blblah bl blahb; blah bl blah bl bl a blah, bla blahb bl: 

    blah blahblah blah bl blah blahblah""") 

options = parser.parse_args() 

這是它是如何工作在2.7和3.4:

$ python test.py -h 
usage: test.py [-h] 

Blahbla bla blah blahh/blahbla (bla blah-blabla) a blahblah bl a blaha-blah 
.blah blah 

Blah blah bla blahblah, bla blahblah blah blah bl blblah bl blahb; blah bl 
blah bl bl a blah, bla blahb bl: 

    blah blahblah blah bl blah blahblah 

optional arguments: 
    -h, --help show this help message and exit 
相關問題