![]() |
力能扛鼎的夕阳 · python字典多键值及重复键值的使用_py ...· 1 年前 · |
![]() |
酷酷的作业本 · Laravel的pluck方法没有返回数据库 ...· 1 年前 · |
![]() |
有情有义的汤圆 · Vue + webpack + ...· 1 年前 · |
![]() |
不羁的苦瓜 · webview - How to ...· 1 年前 · |
![]() |
失望的苹果 · 963%E5%BD%A9%E7%A5%A8% ...· 1 年前 · |
我正在使用
在Python 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()
然而,
删除所有换行符和连续空格。结果看起来像
~/Downloads:52$ python2.7 x.py -h
usage: x.py [-h] [-g {a,b,g,d,e}]
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
如何在帮助文本中插入换行符?
尝试使用
from argparse import RawTextHelpFormatter
parser = ArgumentParser(description='test', formatter_class=RawTextHelpFormatter)
如果只想覆盖one选项,则不应使用
..。相反,子类化
并为应该"raw“处理的选项提供一个特殊的介绍(我使用
):
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()
任何其他调用
帮助不是以
将被正常包装。
这是
我对argparse的改进
..。完整的SmartFormatter还支持将默认值添加到所有选项,以及实用程序描述的原始输入。完整版有它自己的
方法,这样对版本字符串所做的任何格式化操作都会被保留:
parser.add_argument('--version', '-v', action="version",
version="version...\n 42!")
我也遇到过类似的问题(Python 2.7.6)。我试着崩溃
描述
一节分成几行,使用
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
所以
不是一个解决方案。因为它打印源代码中显示的描述,保留所有空格字符(我希望在源代码中保留额外的制表符以提高可读性,但我不想将它们全部打印出来。另外,原始格式化程序不会在行太长时换行,例如超过80个字符)。
感谢@Anton,他启发了正确的方向
以上
..。但该解决方案需要稍加修改才能格式化
描述
部分。
无论如何,自定义格式化程序是必需的。我扩展了现有的
类和重写
方法如下:
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
Second paragraph
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
另一种简单的方法是包含
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 ...
我想在描述文本中使用手动换行符和自动换行;但是这里的建议对我都不起作用-所以我最终修改了这里的答案中给出的SmartFormatter类;尽管argparse方法名不是公共API,但下面是我所拥有的(作为一个名为的文件
):
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
从上面描述的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
请注意,奇怪的是,格式化程序
_
传递给顶级解析器的类参数不会被sub继承
_
解析器,则必须为每个创建的sub再次传递它。
_
解析器。
前言
对于这个问题,
对我很有帮助。
现在,我想分享一下如何使用
..。
我知道这可能与问题无关,
但这些问题已经困扰了我一段时间。
所以我想分享我的经验,希望能对某些人有所帮助。
我们开始吧。
第三方模块
colorama
:对于更改文本颜色:
使ANSI转义字符序列(用于生成彩色终端文本和光标定位)在MS Windows下工作
示例
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)
其中的类
如下所示
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
下面的python 3格式化程序附加默认值并保留行长度。
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter, \
RawTextHelpFormatter
import textwrap
class CustomArgumentFormatter(ArgumentDefaultsHelpFormatter, RawTextHelpFormatter):
"""Formats argument help which maintains line length restrictions as well as appends default value if present."""
def _split_lines(self, text, width):
text = super()._split_lines(text, width)
new_text = []
# loop through all the lines to create the correct wrapping for each line segment.
for line in text:
if not line:
# this would be a new line.
new_text.append(line)
continue
# wrap the line's help segment which preserves new lines but ensures line lengths are