1 解析命令行参数
- argparse介绍:
argparse 是 Python 内置的一个用于命令项选项与参数解析的模块;
argparse 将会从 sys.argv 中解析出这些参数,并自动生成帮助和使用信息
- argparse使用:
ArgumentParser对象的相关属性。
全部参数见下表:
属性 | 解释 | 默认值 |
prog | 程序的名称 | sys.argv[0] |
usage | 描述程序用途的字符串 | 自动生成 |
description | 在参数帮助文档之前显示的文本 | None |
epilog | 在参数帮助文档之后显示的文本 | 同上 |
parents | 一个ArgumentPaser对象的列表,它们的参数也应包含在内 | [] |
prefix_chars | 可选参数的前缀字符集合 | '-' |
formatter_class | 用于自定义帮助文档输出格式的类 | argparse.HelpFormatter |
fromfile_prefix_chars | 当需要从文件中读取其他参数时,用于标识文件名的前缀字符集合 | None |
argument_default | 参数的全局默认值 | 同上 |
conflict_handler | 解决冲突选项的策略 | ‘error’ |
add_help | 为解析器添加一个 -h/--help选项 | True |
llow_abbrev | 如果缩写是无歧义的,则允许缩写长选项(版本>=python3.5) | True |
exit_on_error | 决定当错误发生时是否让ArgumentParser附带错误信息退出(版本>=python3.9) | 同上 |
#导入argparse模块
import argparse
# 创建解析器
parser = argparse.ArgumentParser(description='desc')
# 添加整型参数
parser.add_argument('--integers', type=int, default=0, help='input an integer')
# 解析参数parse_args()通常不带参数调用,ArgumentParser将自动从sys.argv确定命令行参数。
args = parser.parse_args()
print(args)
#返回一个具有integers属性的对象 Namespace(integers=0).
源码中的add_argument()方法解析:
ArgumentParser.add_argument(name or flags...,
action='',
nargs='',
const,
default,
type,
choices,
required,
help,
metavar,
dest)
add_argument(‘-f’, ‘–foo’) # 可选参数
add_argument(‘foo’) # 位置参数
action #该action关键字参数指定的命令行参数应该如何处理
action = ‘store’ # 默认操作仅存储参数的值,可以不写
action = ‘store_const’ # 将存储由const关键字参数指定的值
action = ‘store_true’ # 这些是’store_const’分别存储值True和False的情况下使用
action = ‘store_false’
action = ‘append’ # 存储一个列表,并将命令行的每个参数值附加到列表中
action = ‘append_const’ # 存储一个列表,并将const关键字参数指定的值附加到列表中,可用于多个参数需要将常量存储到同一列表,const默认参数为None
action = ‘count’ # 计算关键字参数出现的次数
action = ‘extend’ # 存储一个列表,并将每个参数值添加到列表中
nargs : 将单个命令行参数与要执行的单个操作相关联,并收集到一个列表中
nargs = N(一个整数) # nargs=2,命令行python test.py --foo a b 将a,b收集到一个列表中
nargs = ? # 表示从命令行使用一个参数,作为选项参数的值,如果命令行指定了参数的值则使用(python test.py --foo xx),如果不存在命令行参数(python test.py),使用default默认值,如果存在可选项参数(python test.py --foo),但是没有指定参数值,会使用const的值。
nargs = * # 存在的所有命令行参数都收集到一个列表中
nargs = + # 跟*用法一样,都会收集到一个列表中,但是如果没有命令行参数则会报错
default # 指定默认值
type # 指定类型 int float等
choices # 指定某些命令行参数应从一组受限制的值中选择,如果参数不是可接受的值一直,则报错
required=True # 指定参数值为必填
help #帮助信息说明
代码示例,
实现输入数字,返回指定值
import argparse
# 创建解析对象,并添加描述信息
parser = argparse.ArgumentParser(description = "输出数字2倍数")
# 添加命令行参数“num",还有该参数的帮助信息,参数类型
parser.add_argument("num", help="2*num a given number", type = int)
# 进行解析
args = parser.parse_args()
# 实现功能
print(args.square*2)
- Python 命令行解析
手工编写 Python 命令行解析,支持 ‘-x’ 或者 ‘–x’ 类型选项处理,如果没有指定值则设置为True
# -*- coding: UTF-8 -*-
import sys
def error(info):
print(info)
sys.exit(0)
def parse_option(token):
if len(token) == 0 or len(token) == 1 or token[0] != '-':
error("格式错误,选项长度至少大于2并且第一个字符必须是 '-'")
if token[1] != '-':
return token[1:]
if len(token) == 2 or token[2] == '-':
error("格式错误,不支持空选项 '--' 或则三横杆选项 '---x' ")
return token[2:]
def parse_value(token):
if token is None:
return True
if len(token) == 0:
return True
if token[0] == '-':
error('格式错误')
else:
return token
if __name__ == '__main__':
count = len(sys.argv)
options = {}
# TODO(You): 请在此使用 parse_option 和 parse_value 解析命令行
for option in options:
value = options[option]
print("{}={}".format(option, value))
请选出下列能正确实现这一功能的选项。
A.
i = 1
while i < count:
token = sys.argv[i]
next_token = None
if i+1 < count:
next_token = sys.argv[i+1]
option = parse_option(token)
value = parse_value(next_token)
options[option] = value
i += 1
B.
i = 1
while i < count:
token = sys.argv[i]
next_token = None
if i+1 < count:
next_token = sys.argv[i+1]
option = parse_value(token)
value = parse_option(next_token)
options[option] = value
i += 1
C.
i = 1
while i < count:
token = sys.argv[i]
next_token = None
if i+1 < count:
next_token = sys.argv[i+1]
i = i + 1
option = parse_option(token)
value = parse_value(next_token)
options[option] = value
i += 1
D.
i = 1
while i < count:
token = sys.argv[i]
next_token = None
if i+1 < count:
next_token = sys.argv[i+1]
i = i + 1
option = parse_option(token)
value = parse_value(next_token)
options[option] = value
# C正确
- Python命令行解析(二)
使用 optparse 库配置指定命令行选项,并解析命令行 1. 选项 ‘-s’ 和选项 ‘–server’ 等价 2. 选项 ‘–host’ 设置默认为 0.0.0.0 3. 选项 ‘–port’ 设置默认为 80 4. 选项 ‘–ssl’ 如果指定,则 option.ssl=True
使用 optparse 库配置指定命令行选项,并解析命令行 1. 选项 '-s' 和选项 '--server' 等价 2. 选项 '--host' 设置默认为 0.0.0.0 3. 选项 '--port' 设置默认为 80 4. 选项 '--ssl' 如果指定,则 option.ssl=True
# -*- coding: UTF-8 -*-
from ast import parse
from optparse import OptionParser
if __name__ == "__main__":
parser = OptionParser()
# TODO(You): 请在此添加上述要求的4个命令行参数选项配置
(options, args) = parser.parse_args()
print(f"server={options.server}")
print(f"host={options.host}")
print(f"port={options.port}")
print(f"ssl={options.ssl}")
请选出下列能正确实现这一功能的选项。
A.
parser.add_option(
"-s", "--server",
dest="server",
help="server",
metavar="SERVER"
)
parser.add_option(
"-h", "--host",
dest="host",
help="host",
metavar="HOST"
)
parser.add_option(
'-p', "--port",
dest="port",
help="port",
default='80',
metavar="PORT"
)
parser.add_option(
"--ssl",
dest="ssl",
help="ssl",
action="store_true",
metavar="SSL"
)
B.
parser.add_option(
"-s", "--server",
dest="server",
help="server",
metavar="SERVER"
)
parser.add_option(
"-h", "--host",
dest="host",
help="host",
default='0.0.0.0',
metavar="HOST"
)
parser.add_option(
'-p', "--port",
dest="port",
help="port",
default='80',
metavar="PORT"
)
parser.add_option(
"--ssl",
dest="ssl",
help="ssl",
action="store_true",
metavar="SSL"
)
C.
parser.add_option(
"-s", "--server",
dest="server",
help="server",
metavar="SERVER"
)
parser.add_option(
"-h", "--host",
dest="host",
help="host",
default='0.0.0.0',
metavar="HOST"
)
parser.add_option(
'-p', "--port",
dest="port",
help="port",
default='80',
metavar="PORT"
)
parser.add_option(
"--ssl",
dest="ssl",
help="ssl",
action="store_true",
metavar="SSL"
)
D.
parser.add_option(
"-s", "--server",
dest="server",
help="server",
metavar="SERVER"
)
parser.add_option(
"-h", "--host",
dest="host",
help="host",
default='0.0.0.0',
metavar="HOST"
)
parser.add_option(
'-p', "--port",
dest="port",
help="port",
default='80',
metavar="PORT"
)
parser.add_option(
"--ssl",
dest="ssl",
help="ssl",
metavar="SSL"
)
# C 正确
2 时间日期处理
python中时间处理主要使用的库是datetime
- datetime是内置模块,不需要安装,直接使用
import datetime
2.datetime里面有五个类:
- date类:表示日期的类
- time类:表示时间的类
- datetime类:表示时间日期的类
- timedelta类:表示两个datetime对象的差值
- tzinfo类:表示时区的相关信息
其中最常用的是datetime类,其包含了date类和time类.
3.模块的使用:
datetime的简单使用
#获取当前日期
from datetime import datetime
now = datetime.now()
#获取今天
datetime.today()
#获取指定日期
datetime.date(y,m,d)
datetime.time(h,m,s)
datetime(y,m,d,h)
#输出指定格式
print('strftime():', now.strftime("%Y-%m-%d"))
timedelta的使用
import datetime
now = datetime.now()
y = now + timedelta(days=-1) # 昨天
m = now + timedelta(days=1) # 明天
- 使用案例:输出指定日期是星期几
# python3
#! coding=utf8
from datetime import datetime
year,month,day= 2023,10,6
weekday = ['周一','周二','周三','周四','周五','周六','周日']
i = datetime(year,month,day).weekday()
print(weekday[i])
i = datetime(year,month,day).isoweekday()
print(weekday[i-1])
wday = datetime(year,month,day).strftime('%a')
print(wday)
- 扩展,一个用来计算农历的库
zhdate
安装
pip install zhdate
示例:
#! python3
#! encoding=utf8
from datetime import datetime
import zhdate
'''
pip install zhdate
计算农历, 公历和农历的转换
内置1900-2100的农历数据
'''
date_now = zhdate.ZhDate.today()
print(date_now)
date_1 = zhdate.ZhDate(2022,1,1)
print(date_1)
date_2 = date_1.to_datetime()
print(date_2.date())
#计算距离端午节还有几天
zhdwj = zhdate.ZhDate(2024,5,5)
dwj = zhdwj.to_datetime()
now_day = datetime.now()
total = dwj.toordinal() - now_day.toordinal()
print(f'今天{now_day.strftime("%Y-%m-%d")}距离{zhdwj.chinese()}-端午节还有{total}天')
- Python计时器
便利的 Python 计时器,统计从 0 遍历到 100000 消耗的时间,精确到毫秒
便利的 Python 计时器,统计从 0 遍历到 100000 消耗的时间,精确到毫秒
# -*- coding: UTF-8 -*-
from datetime import datetime
from time import time, mktime
class TimeSpan:
def __init__(self) -> None:
self.start = round(time() * 1000)
def elapse_mill_secs(self):
# TODO(You): 请在此计算从开始到现在的耗时,精确到毫秒
def elapse_secs(self):
return (self.elapse_mill_secs())/1000
if __name__ == '__main__':
s = TimeSpan()
for i in range(0, 100000):
pass
print('耗时: {} 毫秒'.format(s.elapse_mill_secs()))
print('耗时: {} 秒'.format(s.elapse_secs()))
以下实现,错误 的是?。
# A.
def elapse_mill_secs(self):
end = round(time() * 1000)
return end-self.start
# B.
def elapse_mill_secs(self):
end = round(mktime(datetime.now().timetuple())*1000)
return end-self.start
# C.
def elapse_mill_secs(self):
end = round(datetime.now().timestamp() * 1000)
return end-self.start
# D.
def elapse_mill_secs(self):
end = round(time(datetime.now())*1000)
return end-self.start
# D错误
- Python时间加法
从2008年1月开始到本月,遍历每一个月份的1号,并打印信息
# -*- coding: UTF-8 -*-
from datetime import date, timedelta
from calendar import monthrange
def next_month(d):
# TODO(You): 请在此实现计算下一个月的代码
return value
def for_each_month(start, finish, action):
while start < finish:
action(start)
start = next_month(start)
if __name__ == '__main__':
for_each_month(
date(2008, 1, 1),
date.today(),
lambda d: print(d)
)
# 请选出以下实现 错误 的代码。
# A.
offset = monthrange(d.year, d.month)
first_weeky_day, days_in_month = offset
value = d+timedelta(days_in_month)
# B.
offset = monthrange(d.year, d.month)
days_in_month, first_weeky_day = offset
value = d+timedelta(days_in_month)
# C.
offset = monthrange(d.year, d.month)
days_in_month = offset[1]
value = d+timedelta(days_in_month)
# D.
days_in_month = monthrange(d.year, d.month)[1]
value = d+timedelta(days_in_month)
# B错误
题目逻辑分析:
1、定义了一个 next_month 函数,用于计算下一个月的日期。
2、next_month 函数的输入参数是一个日期对象 d。
3、使用 monthrange 函数计算出当前月份的天数和第一天是星期几。
4、提取出当前月份的天数,加上一个月之后的天数,得到下一个月的日期。
5、返回下一个月的日期。
6、定义了一个 for_each_month 函数,用于遍历一个时间段内的每一个月份。
7、for_each_month 函数的输入参数包括开始日期、结束日期和一个处理函数 action。
8、在 for_each_month 函数中,使用 next_month 函数计算下一个月份的日期,并调用 action 处理函数处理该日期。
9、在 main 函数中,使用 for_each_month 函数遍历从 2008 年 1 月开始到当前日期的每一个月份,并输出该月份的日期。
题目逐段分析:
from datetime import date, timedelta
from calendar import monthrange
# 定义一个函数,用于计算下一个月的日期
def next_month(d):
# 获取当前日期所在月的天数信息
offset = monthrange(d.year, d.month)
# 获取当前月份的总天数
days_in_month = offset[1]
# 获取下一个月的日期,使用 timedelta 函数加上当前月份的总天数即可
value = d + timedelta(days_in_month)
# 返回计算出的下一个月的日期
return value
# 定义一个函数,用于对指定日期区间内的每个月进行遍历并执行指定的操作
def for_each_month(start, finish, action):
# 不断对 start 进行遍历,直到达到指定的 finish 日期
while start < finish:
# 执行指定的操作
action(start)
# 获取下一个月的日期
start = next_month(start)
# 主程序入口
if __name__ == '__main__':
# 遍历指定日期区间内的每个月份
for_each_month(
date(2008, 1, 1),
date.today(),
lambda d: print(d)
)
题目中的引入知识:
1、monthrange(year, month) ,是 Python 标准库中 calendar 模块的函数之一,用于获取给定年份和月份的月份天数和第一天的星期几。该函数返回一个二元组,第一个元素是该月份的天数,第二个元素是该月份第一天的星期几,星期一是0,星期日是6。
例如, calendar.monthrange(2022, 2) 返回 (28, 1),表示2022年2月有28天,第一天是星期二。
2、序列解包,是指将一个序列(包括列表、元组、字符串、集合等)中的元素,按照顺序赋值给多个变量的过程。具体地说,就是将一个序列按照位置顺序,依次赋值给一系列变量,变量的个数应该和序列中的元素个数相等。序列解包的实际应用场景很多,比如函数返回多个值、交换两个变量的值、遍历字典等等。
例如,我们有一个元组(1,2,3),我们可以通过序列解包将其赋值给三个变量:
a, b, c = (1, 2, 3)
print(a, b, c) # 输出:1 2 3
答案中错误的代码分析:
offset = monthrange(d.year, d.month)
# 1、monthrange返还了d.year和d.month两个值
# 2、用序列解包的方式把赋值给days_in_month, first_weeky_day
# 然鹅:days_in_month的为d.year取错了,first_weeky_day没有使用。
days_in_month, first_weeky_day = offset
value = d+timedelta(days_in_month)
答案中正确的代码分析:
offset = monthrange(d.year, d.month)
# 取值正确,但first_weeky_day没有使用。
first_weeky_day, days_in_month = offset
value = d+timedelta(days_in_month)
# 最优代码,省略了offset转存的过程。
days_in_month = monthrange(d.year, d.month)[1]
value = d+timedelta(days_in_month)
在 Python 中,我们可以使用星号(*)来表示序列解包中的“剩余部分”,即将多余的元素赋值给一个列表。比如,如果一个序列中有 5 个元素,而你只想取前两个元素,同时也想把剩余的元素存入一个列表中,可以这样写:a, b, *rest = [1, 2, 3, 4, 5]。这样,a 和 b 分别被赋值为 1 和 2,而 rest 则被赋值为 [3, 4, 5]。