पायथॉन एर्गपर्स: हेल्प टेक्स्ट में न्यूलाइन कैसे डालें?


340

मैं इनपुट विकल्पों को पार्स करने के लिए argparseपायथन 2.7 में उपयोग कर रहा हूं । मेरा एक विकल्प एक बहुविकल्पी है। मैं इसके मदद पाठ में एक सूची बनाना चाहता हूं, जैसे

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()

हालाँकि, argparseसभी नए सिरे और लगातार रिक्त स्थान। परिणाम जैसा दिखता है

~ / डाउनलोड: 52 $ python2.7 x.py -h
उपयोग: x.py [-h] [-g {a, b, g, d, e}]

परीक्षा

वैकल्पिक तर्क:
  -h, --help इस मदद संदेश और बाहर निकलें दिखाएँ
  -g {ए, बी, जी, डी, ई} कुछ विकल्प, जहां एक = अल्फा बी = बीटा जी = गामा डी = डेल्टा ई
                  = एप्सिलॉन

हेल्प टेक्स्ट में न्यूलाइन्स कैसे डालें?


मेरे पास अजगर 2.7 नहीं है, इसलिए मैं अपने विचारों का परीक्षण कर सकता हूं। कैसे ट्रिपल उद्धरणों में मदद पाठ का उपयोग करने के बारे में ("" "" "")। क्या नई लाइनें इसके इस्तेमाल से बच जाती हैं?
pyfunc 8

4
@pyfunc: नहीं। argparseइंटरप्रेटर द्वारा स्ट्रिपिंग रनटाइम में की जाती है, इसलिए स्विच करने """..."""से मदद नहीं मिलेगी।
kennytm 8

यह मेरे लिए काम किया
इलायची

जवाबों:


393

प्रयोग करके देखें RawTextHelpFormatter:

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

6
मुझे लगता है कि यह नहीं है। आप इसे उप-वर्ग कर सकते हैं, लेकिन दुर्भाग्य से Only the name of this class is considered a public API. All the methods provided by the class are considered an implementation detail. शायद यह एक महान विचार नहीं है, हालांकि यह कोई फर्क नहीं पड़ता, क्योंकि 2.7 का मतलब अंतिम 2.x अजगर है और आपको वैसे भी 3.x के लिए बहुत सी चीजों को रिफैक्ट करने की उम्मीद होगी। मैं वास्तव में 2.6 के साथ argparseस्थापित कर रहा हूँ easy_installताकि प्रलेखन अपने आप पुराना हो जाए।
अंतर्निर्मित

3
कुछ लिंक: अजगर 2.7 के लिए , और अजगर 3. * । 2.6 पैकेज को, इसके विकी के अनुसार , आधिकारिक 2.7 के साथ पालन करना चाहिए । डॉक से: "रॉटरेसलाइफ हेल्पफ़ॉर्मर को फ़ॉर्मेटर_क्लास के रूप में पास करना = इंगित करता है कि विवरण और एपिलॉग पहले से ही सही ढंग से फ़ॉर्मेट किए गए हैं और लाइन-लिपटे नहीं होने चाहिए"
स्टीफनो

83
इसके बजाय formatter_class = को आज़माएं RawDescriptionHelpFormatterजो केवल मदद पाठ के बजाय विवरण और उपसंहार पर काम करता है।
मार्चु

3
मैंने देखा है कि इसके साथ RawTextHelpFormatter, अग्रणी और अनुगामी नई सूचियाँ हटा दी जाती हैं। इसके आस-पास काम करने के लिए, आप बस दो या अधिक लगातार न्यूलाइन्स जोड़ सकते हैं; सभी लेकिन एक नई सीमा बच जाएगी।
MrMas

11
आप फॉर्मेटर्स को भी जोड़ सकते हैं, जैसे class Formatter( argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter): passऔर फिर formatter_class=Formatter
टेरी ब्राउन

79

यदि आप केवल एक विकल्प को ओवरराइड करना चाहते हैं, तो आपको उपयोग नहीं करना चाहिए 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|सामान्य रूप से लपेटा जाएगा।

यह अर्गपर्स पर मेरे सुधार का हिस्सा है । पूर्ण SmartFormatter भी सभी विकल्पों में चूक को जोड़ने का समर्थन करता है, और उपयोगिताओं के विवरण के कच्चे इनपुट। पूर्ण संस्करण की अपनी _split_linesविधि है, ताकि उदाहरण के लिए किसी भी स्वरूपण को किया जा सके, ताकि संस्करण को संरक्षित किया जा सके:

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

मैं एक संस्करण संदेश के लिए ऐसा करना चाहता हूं, लेकिन यह स्मार्टफ़ॉर्मर केवल मदद पाठ के साथ काम करता है, विशेष संस्करण पाठ नहीं। parser.add_argument('-v', '--version', action='version',version=get_version_str()) क्या इसे उस मामले में विस्तारित करना संभव है?
mc_electron

@mc_electron SmartFormatter के पूर्ण संस्करण की भी अपनी _split_linesऔर संरक्षित रेखा विराम है (शुरुआत में "R |" को निर्दिष्ट करने की आवश्यकता नहीं है, यदि आप उस विकल्प को चाहते हैं, तो _VersionAction.__call__विधि को पैच करें
Anthon

मैं आपकी टिप्पणी के पहले भाग को पूरी तरह से नहीं कर रहा हूं, हालांकि मैं इसमें देख सकता _VersionAction.__call__हूं कि मैं शायद यह चाहता हूं कि यह केवल parser.exit(message=version)स्वरूपित संस्करण का उपयोग करने के बजाय। क्या ऐसा करने का कोई तरीका है, हालांकि बिना किसी विवाद के एक प्रतिलिपि जारी किए बिना?
mc_electron

@mc_electron मैं उन सुधारों का जिक्र कर रहा हूं, जो मैंने बिटबकेट पर प्रकाशित किए हैं (उत्तर में मेरे सुधार के लिंक के अनुसार)। लेकिन क्या आप भी कर सकते हैं पैच __call__में _VersionActionकार्य करके argparse._VersionAction.__call__ = smart_versionपरिभाषित करने के बादdef smart_version(self, parser, namespace, values, option_string=None): ...
Anthon

महान विचार। मुझे एपिलॉग के रूप में मदद नहीं की और विवरण _split_lines के माध्यम से नहीं लगता है :(
पॉड

31

इसे करने का एक और आसान तरीका है टेक्स्टवैप को शामिल करना

उदाहरण के लिए,

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 ...

11

मैंने इसी तरह के मुद्दे का सामना किया है (पायथन 2.7.6)। मैंने वर्णन अनुभाग को कई पंक्तियों में उपयोग करके तोड़ने की कोशिश की है RawTextHelpFormatter:

parser = ArgumentParser(description="""First paragraph 

                                       Second paragraph

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

options = parser.parse_args()

और मिला:

उपयोग: play-with-argparse.py [विकल्प]

पहला पैराग्राफ 

                        दूसरा अनुच्छेद

                        तीसरा पैराग्राफ

वैकल्पिक तर्क:
  -h, --help इस मदद संदेश और बाहर निकलें दिखाएँ

तो RawTextHelpFormatterसमाधान नहीं है। क्योंकि यह विवरण को प्रिंट करता है क्योंकि यह स्रोत कोड में दिखाई देता है, सभी व्हाट्सएप वर्णों को संरक्षित करते हुए (मैं पठनीयता के लिए अपने स्रोत कोड में अतिरिक्त टैब रखना चाहता हूं, लेकिन मैं उन सभी को प्रिंट नहीं करना चाहता। इसके अलावा कच्चे फॉर्मेटर लाइन को लपेटता नहीं है। बहुत लंबा, उदाहरण के लिए 80 से अधिक अक्षर)।

@Anton का धन्यवाद जिन्होंने ऊपर सही दिशा को प्रेरित किया । लेकिन उस समाधान में विवरण अनुभाग को प्रारूपित करने के लिए मामूली संशोधन की आवश्यकता होती है ।

वैसे भी, कस्टम फॉर्मेटर की जरूरत है। मैंने मौजूदा 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()

आउटपुट है:

उपयोग: play-with-argparse.py [विकल्प]

पहला पैराग्राफ

दूसरा अनुच्छेद

तीसरा पैराग्राफ

वैकल्पिक तर्क:
  -h, --help इस मदद संदेश और बाहर निकलें दिखाएँ

1
यह अद्भुत है --- इस पर लगभग पूरी तरह से मदद तर्क को फिर से लागू करने पर विचार करने और चिंतन करने के बाद हुआ ... मुझे बहुत परेशानी हुई।
पॉल गाउडर

2
उपवर्गीकरण HelpFormatterके बाद से argparse डेवलपर्स केवल गारंटी है कि वर्ग के नाम argparse के भविष्य के संस्करणों में बच जाएगा समस्याग्रस्त है। उन्होंने मूल रूप से खुद को एक खाली चेक लिखा है, ताकि वे विधि के नाम बदल सकें अगर ऐसा करना उनके लिए सुविधाजनक होगा। मुझे यह निराशाजनक लगता है; कम से कम वे कर सकते थे एपीआई में कुछ तरीकों से अवगत कराया।
म्रमास

काफी नहीं ओपी पूछ रहा था, लेकिन वास्तव में मैं क्या चाहता था, धन्यवाद!
हुव वाल्टर्स

2

मैं वर्णन पाठ में दोनों मैनुअल लाइन को तोड़ना चाहता था, और ऑटो रैपिंग; लेकिन यहां दिए गए सुझावों में से किसी ने भी मेरे लिए काम नहीं किया - इसलिए मैंने यहां उत्तरों में दिए गए SmartFormatter वर्ग को संशोधित करना समाप्त कर दिया; इस मुद्दे के साथ argparse विधि नाम सार्वजनिक API नहीं होने के बावजूद, यहाँ मेरे पास क्या है (नामक एक फाइल के रूप में 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

1

ऊपर वर्णित SmartFomatter से शुरू होकर, मैं उस समाधान पर समाप्त हो गया:

class SmartFormatter(argparse.HelpFormatter):
    '''
         Custom Help Formatter used to split help text when '\n' was 
         inserted in it.
    '''

    def _split_lines(self, text, width):
        r = []
        for t in text.splitlines(): r.extend(argparse.HelpFormatter._split_lines(self, t, width))
        return r

ध्यान दें कि शीर्ष स्तर के पार्सर को दिए गए फ़ॉर्मेटर_क्लास तर्क को अजीब तरीके से सबअर्सर्स द्वारा विरासत में नहीं मिला है, प्रत्येक बनाए गए सब_परर्स के लिए इसे फिर से पास करना होगा।


0

प्रस्तावना

इस सवाल के लिए, argparse.RawTextHelpFormatterमेरे लिए उपयोगी है।

अब, मैं साझा करना चाहता हूं कि मैं कैसे उपयोग करूं argparse

मुझे पता है कि यह सवाल से संबंधित नहीं हो सकता है,

लेकिन इन सवालों ने मुझे कुछ समय के लिए परेशान किया है।

इसलिए मैं अपना अनुभव साझा करना चाहता हूं, आशा है कि यह किसी के लिए उपयोगी होगा।

ये रहा।

3 पार्टी मॉड्यूल

colorama : पाठ का रंग बदलने के लिए:pip install colorama

एमएस विंडोज के तहत एएनएसआई एस्केप कैरेक्टर सीक्वेंस (रंगीन टर्मिनल टेक्स्ट और कर्सर पोजिशनिंग बनाने के लिए) काम करता है

उदाहरण

import colorama
from colorama import Fore, Back
from pathlib import Path
from os import startfile, system

SCRIPT_DIR = Path(__file__).resolve().parent
TEMPLATE_DIR = SCRIPT_DIR.joinpath('.')


def main(args):
    ...


if __name__ == '__main__':
    colorama.init(autoreset=True)

    from argparse import ArgumentParser, RawTextHelpFormatter

    format_text = FormatText([(20, '<'), (60, '<')])
    yellow_dc = format_text.new_dc(fore_color=Fore.YELLOW)
    green_dc = format_text.new_dc(fore_color=Fore.GREEN)
    red_dc = format_text.new_dc(fore_color=Fore.RED, back_color=Back.LIGHTYELLOW_EX)

    script_description = \
        '\n'.join([desc for desc in
                   [f'\n{green_dc(f"python {Path(__file__).name} [REFERENCE TEMPLATE] [OUTPUT FILE NAME]")} to create template.',
                    f'{green_dc(f"python {Path(__file__).name} -l *")} to get all available template',
                    f'{green_dc(f"python {Path(__file__).name} -o open")} open template directory so that you can put your template file there.',
                    # <- add your own description
                    ]])
    arg_parser = ArgumentParser(description=yellow_dc('CREATE TEMPLATE TOOL'),
                                # conflict_handler='resolve',
                                usage=script_description, formatter_class=RawTextHelpFormatter)

    arg_parser.add_argument("ref", help="reference template", nargs='?')
    arg_parser.add_argument("outfile", help="output file name", nargs='?')
    arg_parser.add_argument("action_number", help="action number", nargs='?', type=int)
    arg_parser.add_argument('--list', "-l", dest='list',
                            help=f"example: {green_dc('-l *')} \n"
                                 "description: list current available template. (accept regex)")

    arg_parser.add_argument('--option', "-o", dest='option',
                            help='\n'.join([format_text(msg_data_list) for msg_data_list in [
                                ['example', 'description'],
                                [green_dc('-o open'), 'open template directory so that you can put your template file there.'],
                                [green_dc('-o run'), '...'],
                                [green_dc('-o ...'), '...'],
                                # <- add your own description
                            ]]))

    g_args = arg_parser.parse_args()
    task_run_list = [[False, lambda: startfile('.')] if g_args.option == 'open' else None,
                     [False, lambda: [print(template_file_path.stem) for template_file_path in TEMPLATE_DIR.glob(f'{g_args.list}.py')]] if g_args.list else None,
                     # <- add your own function
                     ]
    for leave_flag, func in [task_list for task_list in task_run_list if task_list]:
        func()
        if leave_flag:
            exit(0)

    # CHECK POSITIONAL ARGUMENTS
    for attr_name, value in vars(g_args).items():
        if attr_name.startswith('-') or value is not None:
            continue
        system('cls')
        print(f'error required values of {red_dc(attr_name)} is None')
        print(f"if you need help, please use help command to help you: {red_dc(f'python {__file__} -h')}")
        exit(-1)
    main(g_args)

जहाँ वर्ग FormatTextनिम्न है

class FormatText:
    __slots__ = ['align_list']

    def __init__(self, align_list: list, autoreset=True):
        """
        USAGE::

            format_text = FormatText([(20, '<'), (60, '<')])
            red_dc = format_text.new_dc(fore_color=Fore.RED)
            print(red_dc(['column 1', 'column 2']))
            print(red_dc('good morning'))
        :param align_list:
        :param autoreset:
        """
        self.align_list = align_list
        colorama.init(autoreset=autoreset)

    def __call__(self, text_list: list):
        if len(text_list) != len(self.align_list):
            if isinstance(text_list, str):
                return text_list
            raise AttributeError
        return ' '.join(f'{txt:{flag}{int_align}}' for txt, (int_align, flag) in zip(text_list, self.align_list))

    def new_dc(self, fore_color: Fore = Fore.GREEN, back_color: Back = ""):  # DECORATOR
        """create a device context"""
        def wrap(msgs):
            return back_color + fore_color + self(msgs) + Fore.RESET
        return wrap

यहां छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.