argpase模块
一个可执行文件或者脚本都可以接受参数
$ ls -l /etc/
/etc #位置参数
-l #是选项参数
如何把这些参数传递给程序?
从3.2开始python提供强大的参数分析模块argparse
1.参数分类
- 位置参数,参数放在那 需要一个对应的参数位置,比如之前的案例,/etc就是一个参数位置
- 选项参数,必须通过前边是-短选项或者- - 长选项,后边加选项参数,选项参数后也可以是没有参数.
在linux中基本命令都是按照如此进行编写例如
ls -alh /etc/openvpn
ls #为命令
-alh #为短选项参数
/etc/openvpn # 位置参数
2.基本解析
来一段基本操作
import argparse
parser = argparse.ArgumentParser() #获得一个参数解析器
agrs = parser.parse_args() #分析参数
parser.print_help() #打印帮助
#usage: test1.py [-h]
#optional arguments:
# -h, --help show this help message and exit
运行结果
usage: test1.py [-h]
optional arguments:
-h, --help show this help message and exit
通过观察发现 argparse不仅仅做了参数定义和解析,还自动帮助生成了帮助信息,尤其是usage可以看到现在的参数是否是自己想要的.
3.解析器的参数
参数名称 | 说明 |
---|---|
porg | 程序名字,缺省使用sys.argv[0]的basename |
add_help | 自动生成解析器增加-h和- - help选项,默认为True |
description | 为程序工程添加描述 |
import argparse
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list dir or cer') #获得一个参数解析器
agrs = parser.parse_args() #分析参数
parser.print_help() #打印帮助
结果
usage: ls [-h]
list dir or cer
optional arguments:
-h, --help show this help message and exit
位置参数解析
在linux中ls 是查看文件或者目录使用的,然后将查看内容打印到控制台
打印的时候打印的是位置位置传参
测试代码
import argparse
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list dir or cer ')
parser.add_argument('path')
agrs = parser.parse_args()
parser.print_help()
测试结果
usage: ls [-h] path
ls: error: the following arguments are required: path
#来自googel翻译
用法:ls [-h] 路径
ls:错误:需要以下参数:路径
发现需要提供一个path的参数
1.传参
parse_agrs(args=None,namespace=None)
args 是一个参数列表,一个可迭代对象.内部会把可迭代对象转化为list.如果为none则使用命令行传入参数,非None使用args参数的可迭代对象.
测试代码
import argparse
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list dir or cer ')
parser.add_argument('path')
args = parser.parse_args(('/etc',)) #将agrs看作参数列表可迭代对象
print (1,args,args.path)
parser.print_help()
运行结果
D:\python_project\venv\Scripts\python.exe D:/python_project/test1.py
1 Namespace(path='/etc') /etc #默认namespace 为args
usage: ls [-h] path
list dir or cer
positional arguments:
path
optional arguments:
-h, --help show this help message and exit
进程已结束,退出代码为 0
那么通过以上实验发现namespace 存储着args的path属性,那么即可通过args.path进行访问
2.非必须位位置参数
usage: ls [-h] path
ls: error: the following arguments are required: path
以上代码必须传入位置参数否则就会报错!
但是有时候,我们的测试代码ls不需要输入任何位置参数就可显示当前目录下的文件或者文件夹.
测试代码
import argparse
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list dir or cer')
parser.add_argument('path',nargs='?',default='.',help='path help') #位置参数,可有可无,缺省值,帮助
args = parser.parse_args(('/etc',))
print (1,args,args.path)
parser.print_help()
分析代码
引入 argpase , 定义测试代码ls,加入帮助并开启,描述为list
定义非必须要位置参数,path,nargs表示可有可无,default默认为.也就是当前目录,help表示帮助目录中显示,
定义args的path默认参数为/etc,这是一个迭代器会封装成列表可用agrs.path调用
最后打印
测试结果
D:\python_project\venv\Scripts\python.exe D:/python_project/test1.py
1 Namespace(path='/etc') /etc
usage: ls [-h] [path]###这这这 可选参数!!!!
lisr dir or cer
positional arguments:
path path help ##参数描述
optional arguments:
-h, --help show this help message and exit
进程已结束,退出代码为 0
可以看出path 也变成可选参数,没有提供默认值,默认的.为缺省值指当前目录
在parser.add_argument中
-
help代表在帮助文档中参数的描述
-
nargs 表示这个参数接收结果参数
?表示 一个或者没有,可有可无
+表示至少一个
*表示可以任意个
如果是数字则表示数字代表个数
-
default 表示如果不提供参数则就是这个值,一般和? *进行配合,因为他都是可以不提供位置参数
选项参数
-l 的实现
测试代码
import argparse
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='lisr dir or cer')
parser.add_argument('path',nargs='?',default='.',help='path help') #位置参数,可有可无,缺省值,帮助
parser.add_argument('-l',help='list')
args = parser.parse_args(('/etc',))
print (1,args,args.path)
parser.print_help()
测试结果
1 Namespace(l=None, path='/etc') /etc
usage: ls [-h] [-l L] [path]
lisr dir or cer
positional arguments:
path path help
optional arguments:
-h, --help show this help message and exit
-l L list
进程已结束,退出代码为 0
通过测试发现 ls [-h] [-l L] [path] 是可以实现的,但是我们只想实现简单的 -l 后边这个大写L并不想要!那直接加nargs可以吗?
测试:
import argparse
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='lisr dir or cer')
parser.add_argument('path',nargs='?',default='.',help='path help') #位置参数,可有可无,缺省值,帮助
parser.add_argument('-l',nargs=0,help='list')
args = parser.parse_args(('/etc',))
print (1,args,args.path)
parser.print_help()
测试结果:
Traceback (most recent call last):
File "D:/python_project/test1.py", line 18, in <module>
parser.add_argument('-l',nargs=0,help='list')
File "D:\python\python3.8.10\lib\argparse.py", line 1368, in add_argument
action = action_class(**kwargs)
File "D:\python\python3.8.10\lib\argparse.py", line 863, in __init__
raise ValueError('nargs for store actions must be != 0; if you '
ValueError: nargs for store actions must be != 0; if you have nothing to store, actions such as store true or store const may be more appropriate
#ValueError:存储操作的 nargs 必须是!= 0; 如果您没有要存储的内容,则诸如 store true 或 store const 之类的操作可能更合适 来自google翻译
经测试发现无法直接nargs =0 他必须是一个非零的,控制选项参数和位置参数,但是python给出了解决方法,store true 和store const,需要测试,store 是action参数选项中的
测试代码:
import argparse
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='lisr dir or cer')
parser.add_argument('path',nargs='?',default='.',help='path help') #位置参数,可有可无,缺省值,帮助
parser.add_argument('-l',action='store_true',help='list')
args = parser.parse_args(('/etc',))
print (1,args,args.path)
parser.print_help()
测试结果:
D:\python_project\venv\Scripts\python.exe D:/python_project/test1.py
1 Namespace(l=False, path='/etc') /etc
usage: ls [-h] [-l] [path]
lisr dir or cer
positional arguments:
path path help
optional arguments:
-h, --help show this help message and exit
-l list
进程已结束,退出代码为 0
没有问题 -l就可以看到了.
-a的实现
import argparse
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='lisr dir or cer')
parser.add_argument('path',nargs='?',default='.',help='path help') #位置参数,可有可无,缺省值,帮助
parser.add_argument('-l',action='store_true')
parser.add_argument('-a','-all',action='store_true',help='look any')
args = parser.parse_args(('/etc',))
print (1,args,args.path)
parser.print_help()
返回结果:
1 Namespace(a=False, l=False, path='/etc') /etc
usage: ls [-h] [-l] [-a] [path]
lisr dir or cer
positional arguments:
path path help
optional arguments:
-h, --help show this help message and exit
-l
-a, -all look any
进程已结束,退出代码为 0
属性名称
如果想要自定义namespace 可以使用dest参数进行自定义名称
测试代码:
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='lisr dir or cer')
parser.add_argument('path',nargs='?',default='.',help='look dir') #位置参数,可有可无,缺省值,帮助
parser.add_argument('-l','--list',action='store_true',dest='longfmt',help='use loog list format')
parser.add_argument('-a','-all',action='store_true',help='look any')
args = parser.parse_args(('/etc',))
print (1,args,args.path)
parser.print_help()
测试结果:
D:\python_project\venv\Scripts\python.exe D:/python_project/test1.py
1 Namespace(a=False, longfmt=False, path='/etc') /etc #在这
usage: ls [-h] [-l] [-a] [path]
lisr dir or cer
positional arguments:
path look dir
optional arguments:
-h, --help show this help message and exit
-l, --list use loog list format
-a, -all look any
进程已结束,退出代码为 0
需要实验代码:
需要反复测试,反复练习
import argparse
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list dir or cer') #获得一个参数解析器
agrs = parser.parse_args() #分析参数
parser.print_help() #打印帮助
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list dir or cer ')
parser.add_argument('path')
args = parser.parse_args(('/etc',))
print (1,args,args.path)
parser.print_help()
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='lisr dir or cer')
parser.add_argument('path',nargs='?',default='.',help='path help') #位置参数,可有可无,缺省值,帮助
parser.add_argument('-l',nargs=0,help='list')
args = parser.parse_args(('/etc',))
print (1,args,args.path)
parser.print_help()
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='lisr dir or cer')
parser.add_argument('path',nargs='?',default='.',help='path help') #位置参数,可有可无,缺省值,帮助
parser.add_argument('-l',action='store_true',help='list')
args = parser.parse_args(('/etc',))
print (1,args,args.path)
parser.print_help()
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='lisr dir or cer')
parser.add_argument('path',nargs='?',default='.',help='path help') #位置参数,可有可无,缺省值,帮助
parser.add_argument('-l',action='store_true')
args = parser.parse_args(('/etc',))
print (1,args,args.path)
parser.print_help()
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='lisr dir or cer')
parser.add_argument('path',nargs='?',default='.',help='path help') #位置参数,可有可无,缺省值,帮助
parser.add_argument('-l',action='store_true')
parser.add_argument('-a','-all',action='store_true',help='look any')
args = parser.parse_args(('/etc',))
print (1,args,args.path)
parser.print_help()
parser = argparse.ArgumentParser(prog='ls',add_help=True,description='lisr dir or cer')
parser.add_argument('path',nargs='?',default='.',help='look dir') #位置参数,可有可无,缺省值,帮助
parser.add_argument('-l','--list',action='store_true',dest='longfmt',help='use loog list format')
parser.add_argument('-a','-all',action='store_true',help='look any')
args = parser.parse_args(('/etc',))
print (1,args,args.path)
parser.print_help()
作业
实现 ls [-a] [-l] [-h] path 路径
-a 实现查看目录下的文件,包括隐藏文件
-l 查看详细列表
-h 显示文件大小
作业参考:
目前我们上边学习解决了如果自定义参数和传参的问题,但是没有解决业务问题!
需要设计业务
import argparse
from pathlib import Path
from datetime import datetime
import stat
parser = argparse.ArgumentParser(prog='ls' , add_help=False , description='help dir or cer ')
parser.add_argument('path',nargs='?',help='print path',default='.' )
parser.add_argument('-a','--all',action='store_true',dest='all',help='print all ')
parser.add_argument('-l','--list',action='store_true',dest='long',help='print list' )
parser.add_argument('-h','--human-readable',action='store_true',dest='human',help='--human-readable')
parser.add_argument('-r','--reverse',action='store_true',dest='reverse',help='reverse list')
args = parser.parse_args()
print (args)
parser.print_help()
#业务代码 首先需要想 -l 查看目录文件 联想到path
# def listdir(path,all=False):
# p = Path(path)
# # for f in p.iterdir(): #序列化,将路径下的文件变成一个可迭代对象
# # if not all and f.name.startswith('.'): #判断
# # continue
# # yield f.name
# #yield from filter(lambda f:not(not all and f.name.startswith('.')),p.iterdir()) #将以上for进行改造成yield
# #yield from filter (lambda f : all or not f.name.startswith('.'),p.iterdir()) #
# yield from map(lambda x:x.name,filter(lambda f:all or not f.name.startswith('.'),p.iterdir()))
# #分析以上代码 map 传入一个函数和可迭代对象,返回列表,将filter过滤隐藏文件后的本地文件名传入,返回x.name然后通过yield进行返回
# #通过lamdba 进行过滤 p.iterdir 这是将路径进行序列化然后过滤到.开头的文件,返回非.开头的文件
#-a 的实现
def _listdir(path , all,detail,reverse,human):
"""列出详细的文件rwx"""
p = Path(path)
for i in p.iterdir():
if not all and i.name.startswith('.'):
continue #继续的意思
if not detail :
yield (i.name,)
else :
st = i.stat()
mode = stat.filemode(st.st_mode)
mtime = datetime.fromtimestamp(st.st_mtime).strftime('%y %m %d' '%H' '%M' '%S')
size = st.st_size if not human else _gethuman(st.st_size)
yield (mode,st.st_nlink,st.st_uid,st.st_gid,size,mtime,i.name)
# -r的实现,查看文件排序
def listdir(path , all=False,detail=False,reverse=False,human=False):
"""列出详细的文件rwx"""
return sorted(_listdir(path,all,detail,reverse,human),key=lambda x:x[len(x)-1],reverse=reverse)
#-h 的实现
def _gethuman(size= int):
units = 'KMGTP'
depth = 0
while size > 1000 and depth < len(units) -1:
depth += 1
size //= 1000
return "{}{}".format(size,units[depth] if depth else ' ')
if __name__ == '__main__':
args = parser.parse_args()
print (args)
parser.print_help()
files = listdir(args.path,args.all,args.long,args.reverse,args.human)
print (*files,sep='\n')