পাইথন আরগপারস: সহায়তা পাঠ্যে কীভাবে নতুন লাইন ?োকানো যায়?


340

ইনপুট বিকল্পগুলি argparseপার্সিংয়ের জন্য আমি পাইথন ২.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 $ পাইথন 2.7 x.py -h
ব্যবহার: x.py [-h] [-g {এ, বি, জি, ডি, ই}]

পরীক্ষা

alচ্ছিক যুক্তি:
  -h, - সহায়তা এই বার্তাটি দেখান এবং প্রস্থান করুন
  -g {a, b, g, d, e} কিছু বিকল্প, যেখানে a = আলফা বি = বিটা জি = গামা ডি = ডেল্টা ই
                  = এপসিলন

সহায়তা পাঠ্যের মধ্যে কীভাবে নতুন লাইন sertোকানো যায়?


আমার সাথে পাইথন ২.7 নেই তাই আমি আমার ধারণাগুলি পরীক্ষা করতে পারি। ট্রিপল উদ্ধৃতিতে "" "" "" ") সাহায্যের পাঠ্যটি কীভাবে ব্যবহার করবেন। নতুন লাইনগুলি কি এটি ব্যবহার করে বেঁচে আছে?
পাইফুঙ্ক

4
@pyfunc: না। স্ট্রিপিং রানটাইম দ্বারা সম্পন্ন করা হয় argparse, দোভাষী হিসাবে নয়, তাই স্যুইচিং """..."""সাহায্য করবে না।
কেনেটিএম

এটি আমার জন্য কাজ করেছিল
এলাচ

উত্তর:


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. সম্ভবত এটি একটি দুর্দান্ত ধারণা নয়, যদিও এটি বিবেচ্য নয়, যেহেতু ২.7 বলতে বোঝানো হয়েছে সর্বশেষ ২.x অজগর এবং আপনি যেভাবেই 3.x এর জন্য প্রচুর পরিমাণে চুল্লী প্রত্যাশা করবেন বলে আশা করা যায়। আমি argparseইনস্টল থাকা সাথে প্রকৃতপক্ষে ২.6 চালাচ্ছি easy_installযাতে ডকুমেন্টেশন নিজেই পুরানো হয়ে যায়।
অনুপ্রেরণা

3
কিছু লিঙ্ক: পাইথন ২.7 এবং অজগর ৩. * এর জন্য । ২.6 প্যাকেজের উইকি অনুসারে অফিসিয়াল ২.7 মেনে চলতে হবে। দস্তাবেজ থেকে: "RawDescriptionHelpFormatter কে formatmat_class = হিসাবে পাস করা ইঙ্গিত দেয় যে বর্ণনা এবং এপিলোগ ইতিমধ্যে সঠিকভাবে ফর্ম্যাট হয়েছে এবং লাইন-মোড়ানো উচিত নয়"
স্টেফানো

83
পরিবর্তে formatter_class = চেষ্টা করুন RawDescriptionHelpFormatterযা সাহায্যের পাঠ্যের পরিবর্তে কেবল বিবরণ এবং এপিলোগে কাজ করে।
মার্কহু

3
আমি লক্ষ্য করেছি যে এমনকি RawTextHelpFormatter, শীর্ষস্থানীয় এবং অনুসরণযোগ্য নতুন লাইনগুলি সরানো হয়েছে। এটির কাজ করার জন্য, আপনি কেবল দুটি বা ততোধিক টানা নিউলাইনগুলি যুক্ত করতে পারেন; একটি নতুন লাইন ছাড়া সমস্ত বেঁচে থাকবে।
মিঃমাস

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|স্বাভাবিক হিসাবে মোড়ানো হবে।

এটি আরগপার্সে আমার উন্নতির অংশ । সম্পূর্ণ স্মার্টফরম্যাটরটি সমস্ত বিকল্পের ডিফল্ট এবং ইউটিলিটিগুলির বর্ণনার কাঁচা ইনপুট সমর্থন করে। পূর্ণ সংস্করণটির নিজস্ব _split_linesপদ্ধতি রয়েছে, যাতে সংস্করণের স্ট্রিংগুলির জন্য করা কোনও ফর্ম্যাট সংরক্ষণ করা যায়:

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

আমি এটি কোনও সংস্করণ বার্তার জন্য করতে চাই, তবে এই স্মার্টফর্ম্যাটরটি কেবল বিশেষ সংস্করণ পাঠ্যের সাহায্যে সাহায্যের পাঠ্য নিয়ে কাজ করছে বলে মনে হচ্ছে। parser.add_argument('-v', '--version', action='version',version=get_version_str()) এই ক্ষেত্রে কি এটি বাড়ানো সম্ভব?
এমসি_এলেক্ট্রন

@ এমসি_এলেক্ট্রন এর স্মার্টফর্মেটরের সম্পূর্ণ সংস্করণটির নিজস্ব নিজস্ব রয়েছে _split_linesএবং লাইন ব্রেকগুলি সংরক্ষণ করে (শুরুতে "আর |" নির্দিষ্ট করার দরকার নেই, যদি আপনি এই বিকল্পটি চান, তবে _VersionAction.__call__পদ্ধতিটি প্যাচ করুন
এন্টন

আমি আপনার মন্তব্যের প্রথম অংশটি পুরোপুরি ছাঁটাই করছি না, যদিও আমি দেখতে পাচ্ছি _VersionAction.__call__যে আমি সম্ভবত এটি parser.exit(message=version)বিন্যাসিত সংস্করণটি ব্যবহার না করে চাই । আরগপার্সের প্যাচযুক্ত অনুলিপি প্রকাশ না করেই কী কী উপায় আছে?
এমসি_এলেক্ট্রন 20

@ এমসি_এলেক্ট্রন আমি বিটবাকেটে প্রকাশিত উন্নতিগুলি উল্লেখ করছি (উত্তরে আরগপার্সে আমার উন্নতির লিঙ্ক অনুসারে)। কিন্তু আপনাকে প্যাচ করতে __call___VersionActionকরে argparse._VersionAction.__call__ = smart_versionসংজ্ঞায়িত পরdef smart_version(self, parser, namespace, values, option_string=None): ...
Anthon

ভালো বুদ্ধি. এপিলোগ এবং বিবরণ _ স্প্লিট_লাইনগুলি দিয়ে চলবে বলে মনে হচ্ছে না :(
পোড

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

আমি অনুরূপ সমস্যার মুখোমুখি হয়েছি (পাইথন ২.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 [অপশন]

প্রথম অনুচ্ছেদ 

                        দ্বিতীয় অনুচ্ছেদ

                        তৃতীয় অনুচ্ছেদ

alচ্ছিক যুক্তি:
  -h, - সহায়তা এই বার্তাটি দেখান এবং প্রস্থান করুন

সুতরাং RawTextHelpFormatterএকটি সমাধান নয়। কারণ এটি উত্স কোডে প্রদর্শিত হবার সাথে সাথে সমস্ত সাদা অংশের অক্ষর সংরক্ষণ করে বর্ণনা মুদ্রণ করে (পাঠযোগ্যতার জন্য আমি আমার উত্স কোডে অতিরিক্ত ট্যাব রাখতে চাই তবে সেগুলি মুদ্রণ করতে চাই না Also এছাড়াও কাঁচা ফর্ম্যাটারটি যখন লাইনটি আবদ্ধ করে না তখন খুব দীর্ঘ, উদাহরণস্বরূপ 80 টিরও বেশি অক্ষর)।

ধন্যবাদ @ অ্যান্টন যারা উপরের সঠিক দিকটি অনুপ্রাণিত করেছেন । তবে বর্ণন বিভাগটি ফর্ম্যাট করতে সেই সমাধানটিতে সামান্য পরিবর্তন প্রয়োজন ।

যাইহোক, কাস্টম বিন্যাস প্রয়োজন। আমি বিদ্যমান 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

আরগপার্স মডিউল থেকে আসা আসল উত্স কোডের সাথে তুলনা করুন :

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 [অপশন]

প্রথম অনুচ্ছেদ

দ্বিতীয় অনুচ্ছেদ

তৃতীয় অনুচ্ছেদ

alচ্ছিক যুক্তি:
  -h, - সহায়তা এই বার্তাটি দেখান এবং প্রস্থান করুন

1
এটি বিস্ময়কর --- সম্পূর্ণরূপে সহায়তা যুক্তিটি পুরোপুরি পুনর্নির্মাণের বিষয়ে চিন্তাভাবনা করার পরে এই ঘটেছে ... আমাকে বেশিরভাগ ঝামেলা বাঁচিয়েছে।
পল গাউডার 19

2
subclassing HelpFormatterযেহেতু argparse ডেভেলপারদের শুধুমাত্র গ্যারান্টি দিই যে বর্গ নাম argparse ভবিষ্যত সংস্করণে টিকে থাকবে সমস্যাযুক্ত। তারা মূলত একটি ফাঁকা চেক লিখেছেন যাতে তারা পদ্ধতির নাম পরিবর্তন করতে পারে যদি এটি করা তাদের পক্ষে সুবিধাজনক হয়। আমি এই হতাশ খুঁজে পাই; এপিআই-তে কয়েকটি পদ্ধতি উন্মুক্ত করে দেওয়া হয়েছে a
মিঃমাস

ওপি যা চেয়েছিল তা ঠিক নয়, তবে ঠিক আমি যা চেয়েছিলাম, ধন্যবাদ!
হু ওয়াল্টার্স

2

আমি বর্ণনার পাঠ্যটিতে ম্যানুয়াল লাইনের ব্রেক এবং এটির স্বয়ংক্রিয় মোড়ক উভয়ই রাখতে চাইছিলাম; তবে এখানকার কোনও পরামর্শই আমার পক্ষে কার্যকর হয়নি - সুতরাং আমি এখানে উত্তরগুলিতে প্রদত্ত স্মার্টফর্ম্যাটর ক্লাসটি সংশোধন করে শেষ করেছি; আরগপার্স পদ্ধতি পদ্ধতির নামগুলি জনসাধারণের 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

উপরে বর্ণিত স্মার্টফোমেটার থেকে শুরু করে আমি সেই সমাধানটি শেষ করেছি:

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

আমি জানি এটি প্রশ্নের সাথে সম্পর্কিত নাও হতে পারে,

তবে এই প্রশ্নগুলি আমাকে কিছুক্ষণ বিরক্ত করেছে।

তাই আমি আমার অভিজ্ঞতা ভাগ করে নিতে চাই, আশা করি কারও পক্ষে সহায়ক হবে।

এখানে আমরা যাই।

তৃতীয় পক্ষের মডিউল

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

এখানে চিত্র বর্ণনা লিখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.