23argparse

 

成都创新互联主要从事成都做网站、成都网站制作、成都外贸网站建设、网页设计、企业做网站、公司建网站等业务。立足成都服务宁远,十多年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:028-86922220

argparse:

 

习题:

实现ls命令功能,-l、-a、--all、-h选项:

显示路径下的文件列表;

-a和--all显示包含.开头的文件;

-l,详细列表显示;

-h和-l,人性化显示文件大小;

c字符,d目录,-普通文件,l软链接,b块设备,s socket文件,p pipe文件即FIFO;

按文件名排序输出,可和ls的顺序不一样;

详细列表显示时,时间按“年-月-日 时:分:秒”格式显示;

 

-rw-r--r-- 1 root   root    136 May  7 09:45 test.json

 

mode 硬链接 属主 属组 字节 时间 文件名

 

 

 

 

 

 

参数分类:

ls -l /etc

位置参数,参数放在那里,就要对应一个参数位置,如/etc;

选项参数,必须通过前面是-短选项(短选项后面可以没有参数)或--长选项,然后后面的才算它的参数,如-l;

 

程序或脚本在运行时,位置参数必须写,argparse默认的-h可有可无;

 

argparse不仅仅做了参数的定义和解析,还自动帮助生成了帮助信息,尤其是usage,可以看到自定义的参数是否是自己想要的;

 

 

源码:

class ArgumentParser(_AttributeHolder, _ActionsContainer):

    """Object for parsing command line strings into Python objects.

 

    Keyword Arguments:

        - prog -- The name of the program (default: sys.argv[0])   #程序的名字,缺省使用sys.argv[0]

        - usage -- A usage message (default: auto-generated from arguments)

        - description -- A description of what the program does   #为程序功能添加描述

        - epilog -- Text following the argument descriptions

        - parents -- Parsers whose arguments should be copied into this one

        - formatter_class -- HelpFormatter class for printing help messages

        - prefix_chars -- Characters that prefix optional arguments

        - fromfile_prefix_chars -- Characters that prefix files containing

            additional arguments

        - argument_default -- The default value for all arguments

        - conflict_handler -- String indicating how to handle conflicts

        - add_help -- Add a -h/-help option   #自动为解析器增加-h和--help选项,默认为True

    """

    def __init__(self,

                 prog=None,

                 usage=None,

                 description=None,

                 epilog=None,

                 version=None,

                 parents=[],

                 formatter_class=HelpFormatter,

                 prefix_chars='-',

                 fromfile_prefix_chars=None,

                 argument_default=None,

                 conflict_handler='error',

                 add_help=True):

 

 

    def add_argument(self, *args, **kwargs):

        """

        add_argument(dest, ..., name=value, ...)

        add_argument(option_string, option_string, ..., name=value, ...)

        """

 

argparse中add_argument()的action参数,内置6种动作可在解析到一个参数时进行触发:

store_true|store_false   #保存相应的布尔值,用于实现布尔开关

store   #默认,保存参数值,可能会先将参数值转换成另一个数据类型,若没显式指定则为默认

store_const   #用于实现非布尔值的命令行标记,保存一个被定义为参数规格的值

append   #将值保存到一个列表中,若参数重复出现,则保存多个值

append_const   #将定义在参数规格中的值保存到一个列表中

version   #打印关于程序的版本信息,然后退出

 

parser = argparse.ArgumentParser(prog='ls', add_help=True, description='list directory contents')

parser.add_argument('path', nargs='?', default='.', help='path help')

# parser.add_argument('-l')

# parser.add_argument('-l', nargs='?')

parser.add_argument('-l', action='store_true', help='use a long listing format')

parser.add_argument('-a', '--all', action='store_true', help='show all files,do not ignore entries starting with .')   #长短选项可同时给出

args = parser.parse_args()

print(args)

parser.print_help()

 

 

例:

tests.py

import argparse

 

parser = argparse.ArgumentParser()   #获得一个参数解析器

args = parser.parse_args()   #分析参数

parser.print_help()   #打印帮助

 

>python tests.py -h

usage: tests.py [-h]

 

optional arguments:

  -h, --help  show this help message and exit

 

 

例:

import argparse

 

parser = argparse.ArgumentParser(prog='ls', add_help=True, description='list directory contents')

parser.add_argument('path')   #path为位置参数,必须提供,否则报error: the following arguments are required

 

args = parser.parse_args()

print(args)

 

s>python tests.py

usage: ls [-h] path

ls: error: the following arguments are required: path

 

 

例:

import argparse

 

parser = argparse.ArgumentParser(prog='ls', add_help=True, description='list directory contents')

parser.add_argument('path')

 

args = parser.parse_args(('e:/',))   #分析参数,同时传入可迭代的参数,('/etc'.split())或(('/etc'),)或('/etc -all'.split())或(('/etc/','-lah'));Namespace(path='e:/')里的path可通过Namespace对象访问,如args.path

print(args)   #打印名词空间中收集的参数

 

>python tests.py

Namespace(path='e:/')

 

 

例:

import argparse

 

parser = argparse.ArgumentParser(prog='ls', add_help=True, description='list directory contents')

parser.add_argument('path', nargs='?', default='.', help='path help')   #default,给path提供默认值,当前路径,path也变成可选的;nargs表示这个参数接收结果参数,?表示可有可无;help表示帮助文档中这个参数的描述

 

args = parser.parse_args()

print(args)

 

>python tests.py

Namespace(path='.')

 

 

 

-l和-a的实现:

 

parser.add_argument('-l')   #效果为

Namespace(l=None, path='.')

usage: ls [-h] [-l L] [path]

 

parser.add_argument('-l', nargs='?')   #效果为

Namespace(l=None, path='.')

usage: ls [-h] [-l [L]] [path]

 

parser.add_argument('-l', action='store_true')   #效果为

Namespace(l=False, path='.')

usage: ls [-h] [-l][path]

 

例:

parser = argparse.ArgumentParser(prog='ls', add_help=False, description='list directory contents')

parser.add_argument('path', nargs='?', default='.', help='path help')

parser.add_argument('-l', action='store_true', help='use a long listing format')

parser.add_argument('-a', '--all', action='store_true', help='show all files,do not ignore entries starting with .')

parser.add_argument('-h', action='store_true', help='making readable easily')

 

if __name__ == '__main__':

    args = parser.parse_args()

    print('args=', args)

    # parser.print_help()

    print(args.path, args.l, args.h, args.all)

 

>python tests.py -l -a .

args= Namespace(all=True, h=False, l=True, path='.')

. True False True

 

 

 

版本1:

import argparse

from pathlib import Path

import datetime

 

import win_unicode_console

win_unicode_console.enable()

 

 

def _convert_mode(mode: int):

    modelst = ['r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x']   #modelst = list('rwx'*3)

    modestr = bin(mode)[-9:]

    # print(modestr)

    ret = ''

    for i, c in enumerate(modestr):

        if c == '1':

            ret += modelst[i]

        else:

            ret += '-'

    return ret

 

def _convert_human(size: int):

    # units =  [' ', 'K', 'M', 'G', 'T', 'P']   # units = list(' KMGTP')

    units = ' KMGTP'

    depth = 0

    while size >= 1000:

        size = size // 1000

        depth += 1

    return '{}{}'.format(size, units[depth])

 

def _convert_type(file:Path):

    ret = ''

    if file.is_dir():

        ret = 'd'

    elif file.is_symlink():

        ret = 'l'

    elif file.is_socket():

        ret = 's'

    elif file.is_block_device():

        ret = 'b'

    elif file.is_char_device():

        ret = 'c'

    else:

        ret = '-'

    return ret

 

def showdir(path: str='.', detail=False, all=False, human=False) -> list:

    p = Path(path)

    for file in p.iterdir():

        # if not all:

        #     if file.name.startswith('.'):

        #         continue

        if not all and file.name.startswith('.'):

                continue

 

        if detail:

            st = file.stat()

            # print(st)   #os.stat_result(st_mode=33206, st_ino=7599824371282335, st_dev=178462745, st_nlink=1, st_uid=0, st_gid=0, st_size=47, st_atime=1551941978, st_mtime=1551941978, st_ctime=1551928586)

            h = str(st.st_size)

            if human:

                h = _convert_human(st.st_size)

            # drwxr-xr-x 9 ane  ane  4.0K Apr 11 02:40 apache-tomcat-7.0.67

            # (33206, 1, 0, 0, 3031, 1557296696.6941395, 'tests.py')

            # yield (st.st_mode, st.st_nlink, st.st_uid, st.st_gid, st.st_size, st.st_atime, file.name)

            yield (_convert_type(file) + _convert_mode(st.st_mode), st.st_nlink, st.st_uid, st.st_gid, h,

                   datetime.datetime.fromtimestamp(st.st_atime).strftime('%Y-%m-%d %H:%M:%S'), file.name)

        else:

        # print(file.name)

            yield file.name

 

# print(showdir.__annotations__)

 

parser = argparse.ArgumentParser(prog='ls', add_help=False, description='list directory contents')

parser.add_argument('path', nargs='?', default='.', help='path help')

parser.add_argument('-l', action='store_true', help='use a long listing format')

parser.add_argument('-a', '--all', action='store_true', help='show all files,do not ignore entries starting with .')

parser.add_argument('-h', action='store_true', help='making readable easily')

 

if __name__ == '__main__':

    args = parser.parse_args()

    print('args=', args)

    # parser.print_help()

    print('path={} -l={} -h={} -a={}'.format(args.path, args.l, args.h, args.all))

 

    for file in showdir(args.path, detail=args.l, all=args.all, human=args.h):

        print(file)

 

 

版本2:

1、使用stat模块,

In [29]: help(stat.filemode)

Help on built-in function filemode in module _stat:

filemode(...)

    Convert a file's mode to a string of the form '-rwxrwxrwx'

 

In [24]: p = Path('gis.log')

In [25]: p.stat

Out[25]:

In [26]: p.stat()

Out[26]: os.stat_result(st_mode=33206, st_ino=1970324837080203, st_dev=178462745, st_nlink=1, st_uid=0, st_gid=0, st_size=70330, st_atime=1550905696, st_mtime=1550905642, st_ctime=1550905696)

In [27]: p.stat().st_mode

Out[27]: 33206

In [28]: stat.filemode(p.stat().st_mode)

Out[28]: '-rw-rw-rw-'

 

2、整合代码,用到yield from;

 

 

import argparse

from pathlib import Path

import datetime

import stat

 

import win_unicode_console

win_unicode_console.enable()

 

parser = argparse.ArgumentParser(prog='ls', add_help=False, description='list directory contents')

parser.add_argument('path', nargs='?', default='.', help='path help')

parser.add_argument('-l', action='store_true', help='use a long listing format')

parser.add_argument('-a', '--all', action='store_true', help='show all files,do not ignore entries starting with .')

parser.add_argument('-h', action='store_true', help='making readable easily')

 

 

def showdir(path: str='.',  detail=False, all=False, human=False) -> list:

    # modelst = ['r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x']  # modelst = list('rwx'*3)

    # def _convert_mode(mode: int):

    #     modestr = bin(mode)[-9:]

    #     # print(modestr)

    #     ret = ''

    #     for i, c in enumerate(modestr):

    #         if c == '1':

    #             ret += modelst[i]

    #         else:

    #             ret += '-'

    #     return ret

 

    def _convert_human(size: int):

        # units =  [' ', 'K', 'M', 'G', 'T', 'P']   # units = list(' KMGTP')

        units = ' KMGTP'

        depth = 0

        while size >= 1000:

            size = size // 1000

            depth += 1

        return '{}{}'.format(size, units[depth])

 

    # def _convert_type(file:Path):

    #     ret = ''

    #     if file.is_dir():

    #         ret = 'd'

    #     elif file.is_symlink():

    #         ret = 'l'

    #     elif file.is_socket():

    #         ret = 's'

    #     elif file.is_block_device():

    #         ret = 'b'

    #     elif file.is_char_device():

    #         ret = 'c'

    #     else:

    #         ret = '-'

    #     return ret

 

    def _showdir(path: str='.', detail=False, all=False, human=False) -> list:

        p = Path(path)

        for file in p.iterdir():

            # if not all:

            #     if file.name.startswith('.'):

            #         continue

            if not all and file.name.startswith('.'):

                    continue

 

            if detail:

                st = file.stat()

                # print(st)   #os.stat_result(st_mode=33206, st_ino=7599824371282335, st_dev=178462745, st_nlink=1, st_uid=0, st_gid=0, st_size=47, st_atime=1551941978, st_mtime=1551941978, st_ctime=1551928586)

                h = str(st.st_size)

                if human:

                    h = _convert_human(st.st_size)

                # drwxr-xr-x 9 ane  ane  4.0K Apr 11 02:40 apache-tomcat-7.0.67

                # (33206, 1, 0, 0, 3031, 1557296696.6941395, 'tests.py')

                # yield (st.st_mode, st.st_nlink, st.st_uid, st.st_gid, st.st_size, st.st_atime, file.name)

                # yield (_convert_type(file) + _convert_mode(st.st_mode), st.st_nlink, st.st_uid, st.st_gid, h,

                       # datetime.datetime.fromtimestamp(st.st_atime).strftime('%Y-%m-%d %H:%M:%S'), file.name)

                yield (stat.filemode(st.st_mode), st.st_nlink, st.st_uid, st.st_gid, h,

                       datetime.datetime.fromtimestamp(st.st_atime).strftime('%Y-%m-%d %H:%M:%S'), file.name)

            else:

            # print(file.name)

                yield file.name

 

    yield from sorted(_showdir(path, detail, all, human), key=lambda x: x[len(x)-1])

 

# print(showdir.__annotations__)

 

if __name__ == '__main__':

    args = parser.parse_args()

    print('args=', args)

    # parser.print_help()

    print('path={} -l={} -h={} -a={}'.format(args.path, args.l, args.h, args.all))

 

    for file in showdir(args.path, detail=args.l, all=args.all, human=args.h):

        print(file)

 

 

>python tests.py -lah .

args= Namespace(all=True, h=True, l=True, path='.')

path=. -l=True -h=True -a=True

('-rw-rw-rw-', 1, 0, 0, '47 ', '2019-03-07 14:59:38', '__init__.py')

('drwxrwxrwx', 1, 0, 0, '4K', '2019-04-02 17:15:21', '__pycache__')

('-rw-rw-rw-', 1, 0, 0, '209 ', '2019-03-07 14:42:00', 'admin.py')

('-rw-rw-rw-', 1, 0, 0, '1K', '2019-04-01 13:36:40', 'adminx.py')

('-rw-rw-rw-', 1, 0, 0, '119 ', '2019-03-07 14:59:03', 'apps.py')

('-rw-rw-rw-', 1, 0, 0, '854 ', '2019-03-27 15:12:48', 'forms.py')

('drwxrwxrwx', 1, 0, 0, '4K', '2019-03-07 13:46:16', 'migrations')

('-rw-rw-rw-', 1, 0, 0, '2K', '2019-03-28 16:32:33', 'models.py')

('-rw-rw-rw-', 1, 0, 0, '4K', '2019-05-08 16:05:48', 'tests.py')

('-rw-rw-rw-', 1, 0, 0, '786 ', '2019-03-28 16:10:02', 'urls.py')

('-rw-rw-rw-', 1, 0, 0, '9K', '2019-03-30 15:48:10', 'views.py')


网站题目:23argparse
本文链接:http://ybzwz.com/article/jgjhps.html