今天分享又来了呀。ღ( ´・ᴗ・` ) 一起学习进步ღゝ◡╹)ノ♡****
摘要:最近在开发etl工具,其中使用到了Python命令行编程,记录一下。
IMDG:
加油,好好学习,天天向上~ \
Q:
IMDG 重要性?
pycharm中用Terminal打开,这个目录就是项目所在的目录
D:\PythonCode\blibli\WorkTool>
Python运行程序的指令
D:\PythonCode\blibli\WorkTool>python start.py
传入第一个 参数指令
D:\PythonCode\blibli\WorkTool>python start.py hello
1 命令行编程
import sys
# 命令行编程
# 标准库 sys
# 1构建程序的框架 增加一个info指令
print('wtt')
print(sys.argv)
在终端中运行:
D:\PythonCode\blibli\WorkTool>python start.py
wtt
['start.py']
D:\PythonCode\blibli\WorkTool>python start.py hello
wtt
['start.py', 'hello'] 可以看见,这是一个列表,列表里面每个元素都是字符串。第一个元素是我们程序的名字。
D:\PythonCode\blibli\WorkTool>python start.py hello word python
wtt
['start.py', 'hello', 'word', 'python']
import sys
# 命令行编程
# 标准库 sys
# 1构建程序的框架 增加一个info指令
print('wtt')
print(sys.argv)
programName=sys.argv[0] #程序的名字,保存为一个变量
print(programName)
终端执行:
D:\PythonCode\blibli\WorkTool>python start.py
wtt
['start.py']
start.py
# 工作情况分析
import sys
# 命令行编程
# 标准库 sys
# 1构建程序的框架 增加一个info指令
programName=sys.argv[0] #程序的名字,保存为一个变量
if len(sys.argv) >1:
pass
else:
print("命令使用:")
print("\tpython %s 命令[params]" % programName)
---------------------------------
D:\PythonCode\blibli\WorkTool>python start.py
命令使用:
python start.py 命令[params]
# 工作情况分析
import sys
# 命令行编程
# 标准库 sys
# 1构建程序的框架 增加一个info指令
programName = sys.argv[0] # 程序的名字,保存为一个变量
def do_info():
'''info指令'''
pass
if len(sys.argv) > 1:
command = sys.argv[1]
print("command = %s" % command)
if command == "info":
do_info()# 如果命令是info,我想调用函数,执行info要做的事情
else:
print("命令使用:")
print("\tpython %s 命令[params]" % programName)
print("\tpython %s info" % programName)
start1.py
# 工作情况分析
import sys
import xlrd #读取excel的第三方库
# 命令行编程
# 标准库 sys
# 1构建程序的框架 增加一个info指令
# 2给info指令增加第一个参数的实现,传入filepath;输出数据包含的月份信息
def __loadWorkList(filePath): # 私有方法,读取我们的工作簿
wb =xlrd.open_workbook(filename=filePath)
sheet =wb.sheet_by_index(0) #打开第一个sheet
res=[] # 我们要获得结果,结果应该是一个list
for i in range(sheet.nrows)[2:-1]: #对列表进行切片。从第3行开始到倒数第二行。前面去掉2行,后面去掉一行
#sheet.row_values(i) #获取每一行的值
# print(sheet.row_values(i))
res.append(sheet.row_values(i))
return res
def do_info():
"""info指令"""
_help ='正确的指令输入格式: python %s info filepath' %programName # 字符串,来提示用户输入正确的命令行格式
if len(sys.argv) >2: # 传入的第二个指令参数,我希望是程序的路径
filePath = sys.argv[2]
# print(filePath) # 这行是用来测试是否获取到传入的路径的
res =__loadWorkList(filePath)
# months= [r[3][:7] for r in res] # 数据日期:2020-06,2020-06,2020-06,2020-06,2020-06,2020-06
months= {r[3][:7] for r in res} #数据日期: 2020 - 06 推导式写法,每一行拿出来,每一行都是一个列表。取出列表的第三项,截取第三项的前7位。外面符合是{},那就是集合推导式
# print(months) #['2020-06', '2020-06', '2020-06'] {'2020-06'}
print('数据日期:'+','.join(months)) #字符串的join方法,将序列中的每一个元素用,拼接起来
else:
print(_help)
programName=sys.argv[0]
if len(sys.argv) > 1:
command =sys.argv[1]
# print('command =%s'%command)
if command=='info':
do_info()
else:
print('命令使用方法:')
print("\tpython %s COMMAND [PARAMS] " % programName)
print("\tpython %s info " % programName)
学会封装函数,让每一个函数专注于某一项功能。
知道每个函数是用来解决什么问题的。
start2.py
时间戳 代表1970年1月1日0时,到现在这个时间的间隔秒数
# 工作情况分析
import sys
import xlrd
import re
# 命令行编程
# 1 构建程序的框架 增加一个info指令
# 2 给info指令增加第一个参数的实现, filepath命令行参数。输出数据包含的月份信息
# 3 给info指令增加第二个参数 month命令行参数。 规定格式:yyyy-mm格式的字符串 表示年和月 输出每个人工作统计结果
def __loadWorkList(filePath):
wb =xlrd.open_workbook(filename=filePath)
sheet =wb.sheet_by_index(0)
res=[]
for i in range(sheet.nrows)[2:-1]:
#print(sheet.row_values(i))
res.append(sheet.row_values(i))
return res
def calworktimes(date,begin,end): # 3个形参和一个返回值
"""函数逻辑:通过日期、签到、签退时间,计算当天的加班的分钟"""
return 1
def creatPersonData(filePath,month):
res = __loadWorkList(filePath) # 读取内容之后,循环遍历文件的内容
#首先要筛选,这个month的行
res =[line for line in res if line[3][:7] ==month] # 拿到Excel中 每一行的第三位元素(列) 截取前七位
# print(res)
username=None # 先把变量给定义出来,定义为临时变量
user ={} # 用字典数据结构来保存这个人的信息
userDataList=[] # 列表,存放所有人的记录
for r in res: # 遍历所有记录
if username ==r[0]: # 还是这个人 相同的姓名
# 累计当前人的数据
if r[8] =='正常' and r[9] =='正常': # Excel中第8和9个元素(从0开始) 签到状态为‘正常’
user ['zc'] =user ['zc']+1 # 正常 + 1
else:
user['qt'] = user['qt']+1 # 其他 +1
# 没换人时,把数据给累积起来
user ['addwork'] =user ['addwork'] +calworktimes(r[3],r[4],r[5]) # Excel处理加班时长 后面是个函数,加班时间和3个字段有关 日期、签到、签退 所以我们要传入这3个参数
else: # 换人了
if username: # 不是第一行的情况,才保存 等价于 if username !=None:
userDataList.append(user) # 保存 上一个人的数据 到列表中 。假如username是null,还是临时变量的时候,是不能够保存的
# 初始化个人数据
user ={'name':r[0],'zc':0,'qt':0,'addwork':0} # 人名 正常的天数 不正常天数 加班小时数 进行一个数据结构的封装
username =r[0]
for u in userDataList:
print(u)
def do_info():
"""info指令"""
_help ='请输入正确格式的指令: python %s info filePath [YYYY-MM]' %programName
if len(sys.argv) >2:
filePath = sys.argv[2]
if len(sys.argv)>3: #输入的第3个命令行参数 info filePath month
month =sys.argv[3]
print(month)
# 统计每个人的工作数据 使用正则表达式来看看输入的参数是否满足格式的要求!
if not re.match(r'^\d{4}-\d{2}$',month): # 结果是false的情况下 检查月份的格式 \d表示一个数字 {4}重复4次
print(_help) # 打印提示信息
return # 程序一定要结束
else:
creatPersonData(filePath,month) # 函数 从filePath这个文件里读取month这个月份的数据
else:
res =__loadWorkList(filePath)
months= {r[3][:7] for r in res} # 推导式写法
print('数据日期:'+','.join(months))
else:
print(_help)
return #因为输出不符合我们的预期,我们一定要return来使程序结束
programName=sys.argv[0]
if len(sys.argv) > 1:
command =sys.argv[1]
# print('command =%s'%command)
if command=='info':
do_info()
else:
print('命令使用方法:')
print("\tpython %s COMMAND [PARAMS] " % programName)
print("\tpython %s info FILEPATH [YYYY-MM] " % programName)
start3.py
import sys
import xlrd
import re
import datetime
# 命令行编程
# 标准库 sys
# 1 构建程序的框架 增加一个info指令
# 2 给info指令增加第一个参数的实现, filepath输出数据包含的月份信息
# 3 给info指令增加第二个参数 month 是一个yyyy-mm格式的字符串表示年和月 输出每个人工作统计结果
# 4 完善加班时间统计的方法
def __loadWorkList(filePath):
wb = xlrd.open_workbook(filename=filePath)
sheet = wb.sheet_by_index(0)
res = []
for i in range(sheet.nrows)[2:-1]:
# print(sheet.row_values(i))
res.append(sheet.row_values(i))
return res
def calworktimes(date, begin, end):
"""通过日期、签到、签退时间,计算当天的加班的分钟"""
# 我们要知道这个日期是工作日还是休息日
# 加上int(),把返回的字符串转换成整数
week = int(datetime.datetime.strptime(date, '%Y-%m-%d').strftime(
'%w')) # strptime()把字符串转换成时间戳,并且 转换成格式化时间 最后是转换成星期几,星期天是0 星期一是1
minute = 0
if 0 < week < 6: # 周一到周五 也就是工作日
if re.match(r'^\d{2}:\d{2}:\d{2}$', end): # 判断时间格式是否正确
b_time = datetime.datetime.strptime('17:30:00', '%H:%M:%S') # 开始时间
e_time = datetime.datetime.strptime(end, '%H:%M:%S') # 结束时间
if e_time > b_time:
minute = (e_time - b_time).seconds // 60 # 拿到 加班的 间隔的秒数,除以60 拿到分钟
else: # 非工作日
if re.match(r'^\d{2}:\d{2}:\d{2}$', begin) and re.match(r'^\d{2}:\d{2}:\d{2}$', end): # 判断时间格式是否正确
b_time = datetime.datetime.strptime(begin, '%H:%M:%S')
e_time = datetime.datetime.strptime(end, '%H:%M:%S')
if e_time > b_time:
minute = (e_time - b_time).seconds // 60
return minute # 返回直接的加班时间
# calworktimes('2020-07-31',None,None)
# sys.exit(0)
def creatPersonData(filePath, month):
res = __loadWorkList(filePath)
res = [line for line in res if line[3][:7] == month]
print(len(res))
username = None
user = {}
userDataList = []
for r in res: # 遍历所有记录
if username == r[0]: # 还是这个人
# 累计当前人的数据
if r[8] == '正常' and r[9] == '正常':
user['zc'] = user['zc'] + 1
else:
user['qt'] = user['qt'] + 1
user['addwork'] = user['addwork'] + calworktimes(r[3], r[4], r[5])
else: # 换人了
if username: # 不是第一行的情况,才保存
userDataList.append(user) # 保存上一个人的数据
# 初始化个人数据
user = {'name': r[0], 'zc': 0, 'qt': 0, 'addwork': 0}
username = r[0]
with open('data/' + month + '.txt', 'w') as df: #保存下来,在当前目录下,子目录data,以month为名字的txt文件。覆盖内容w。
for u in userDataList: # u 是一个对象,还不能直接往文件里写入。需要格式化下
linestr = '{}|{}|{}|{}'.format(u['name'], u['zc'], u['qt'], u['addwork']) # 用 |进行分割
df.write(linestr + '\n') # 每行有换行符
def do_info():
"""info指令"""
_help = '指令格式: python %s info FILEPATH [YYYY-MM]' % programName
if len(sys.argv) > 2:
filePath = sys.argv[2]
if len(sys.argv) > 3:
month = sys.argv[3]
# 统计每个人的工作数据
if not re.match(r'^\d{4}-\d{2}$', month): # 检查月份的格式
print(_help)
return
else:
creatPersonData(filePath, month)
else:
res = __loadWorkList(filePath)
months = {r[3][:7] for r in res} # 推导式写法
print('数据日期:' + ','.join(months))
else:
print(_help)
return
programName = sys.argv[0]
if len(sys.argv) > 1:
command = sys.argv[1]
# print('command =%s'%command)
if command == 'info':
do_info()
else:
print('命令使用方法:')
print("\tpython %s COMMAND [PARAMS] " % programName)
print("\tpython %s info FILEPATH [YYYY-MM] " % programName)
注意,出现报错
FileNotFoundError: [Errno 2] No such file or directory: 'data/2020-06.txt'
解决方法:
自己在项目中新建个文件夹 data。
python start3.py info e:\6.xls 2020-06
start4.py
# 工作情况分析
import sys
import xlrd
import re
import datetime
# 命令行编程
# 标准库 sys
# 1 构建程序的框架 增加一个info指令
# 2 给info指令增加第一个参数的实现, filepath输出数据包含的月份信息
# 3 给info指令增加第二个参数 month 是一个yyyy-mm格式的字符串表示年和月 输出每个人工作统计结果
# 4 完善加班时间统计的方法
# 5 增加对假期特殊的处理
__以下是对数据获取和加工的功能的代码___
def __loadWorkList(filePath):
wb =xlrd.open_workbook(filename=filePath)
sheet =wb.sheet_by_index(0)
res=[]
for i in range(sheet.nrows)[2:-1]:
# print(sheet.row_values(i))
res.append(sheet.row_values(i))
return res
def loadHoliday():
res =[]
with open('data/holiday.txt','r') as hf : # 读取出来
for line in hf.readlines():
_holiday =line.split('|')[0]
_week = line.split('|')[1]
_type = line.split('|')[2].strip() # 去掉回车符号
#周一到周五,并且是休息日
if (0<int(_week)<6 and _type.lower() =="h") or \
((int(_week)==0 or int(_week)==6) and _type.lower())=='w': # 周六 周日 工作日
res.append(_holiday)
return res
def calworktimes(date,begin,end):
"""通过日期、签到、签退时间,计算当天的加班的分钟"""
# 我们要知道这个日期是工作日还是休息日
week =int(datetime.datetime.strptime(date,'%Y-%m-%d').strftime('%w'))
minute =0
holidays =loadHoliday()
# 周一到周五 非休息日 和 周六周日 的工作日
if (0< week <6 and date not in holidays) or ((week==0 or week==6) and date in holidays): # 不在假期的列表里 满足这些条件的,就是 工作日
if re.match(r'^\d{2}:\d{2}:\d{2}$',end):
b_time =datetime.datetime.strptime('17:30:00','%H:%M:%S')
e_time =datetime.datetime.strptime(end,'%H:%M:%S')
if e_time>b_time:
minute =(e_time-b_time).seconds //60
minute = minute if minute > 60 else 0 # 三元表达式 只有加班时间大于60分钟才算加班,否则时长就是0
else:
if re.match(r'^\d{2}:\d{2}:\d{2}$',begin) and re.match(r'^\d{2}:\d{2}:\d{2}$', end):
b_time = datetime.datetime.strptime(begin, '%H:%M:%S')
e_time = datetime.datetime.strptime(end, '%H:%M:%S')
if e_time>b_time:
minute =(e_time-b_time).seconds //60
minute = minute if minute <480 else 480 # 非工作日,做多加班480分钟
return minute
# calworktimes('2020-07-31',None,None)
# sys.exit(0)
def creatPersonData(filePath,month):
res = __loadWorkList(filePath)
res =[line for line in res if line[3][:7] ==month]
# print(res)
username=None
user ={}
userDataList=[]
for r in res: # 遍历所有记录
if username ==r[0]: # 还是这个人
# 累计当前人的数据
if r[8] =='正常' and r[9] =='正常':
user ['zc'] =user ['zc']+1
else:
user['qt'] = user['qt']+1
user ['addwork'] =user ['addwork'] +calworktimes(r[3],r[4],r[5])
else: # 换人了
if username: # 不是第一行的情况,才保存
userDataList.append(user) # 保存上一个人的数据
# 初始化个人数据
user ={'name':r[0],'zc':0,'qt':0,'addwork':0}
username =r[0]
with open('data/'+month+'.txt','w') as df:
for u in userDataList:
linestr ='{}|{}|{}|{}'.format(u['name'],u['zc'],u['qt'],u['addwork'])
df.write(linestr+'\n')
def do_info():
"""info指令"""
_help ='指令格式: python %s info FILEPATH [YYYY-MM]' %programName
if len(sys.argv) >2:
filePath = sys.argv[2]
if len(sys.argv)>3:
month =sys.argv[3]
# 统计每个人的工作数据
if not re.match(r'^\d{4}-\d{2}$',month): # 检查月份的格式
print(_help)
return
else:
creatPersonData(filePath,month)
else:
res =__loadWorkList(filePath)
months= {r[3][:7] for r in res} # 推导式写法
print('数据日期:'+','.join(months))
else:
print(_help)
return
def do_addholiday(): # 增加节假日
_help ='正确的指令格式: python %s addholiday YYYY-MM-DD TYPE(w:上班 h:休息)'%programName
if len(sys.argv) >3:
_holiday =sys.argv[2] #下划线开头,明确表示这个是局部变量
_type =sys.argv[3]
if not re.match(r'^\d{4}-\d{2}-\d{2}$',_holiday): # 检查月份的格式 如果不是我们希望的日期参数格式
print(_help)
return
if _type.lower() !='w' and _type.lower() !='h': # 让type不区分大小写
print(_help)
return
else:
print(_help)
return
# 将新增的日期放置文件的末尾 希望有个文件来存储我们节假日的信息
holiday_file ='data/holiday.txt'
with open(holiday_file,'a+') as hf : # 往文件的末尾去添加
hf.write('{}|{}|{}\n'.format(_holiday,datetime.datetime.strptime(_holiday,'%Y-%m-%d').strftime('%w'),_type)) # 往文件的最后一行追加 并且增加每行数据时添加换行符
print('增加新的假日:{}{}'.format(_holiday,_type))
def do_listholiday():
with open('data/holiday.txt','r') as hf: # 只读的方式打开文件
for line in hf.readlines():
print('日期:{} 星期 {}{}'.format(line.split('|')[0],line.split('|')[1],
'工作日' if line.split('|')[2].strip()=='w' else "休息日")) # 根据w或者其他的字符,写文字 工作日 or 休息日
programName=sys.argv[0]
if len(sys.argv) > 1:
command =sys.argv[1]
# print('command =%s'%command)
if command=='info':
do_info()
elif command=='addholiday':
do_addholiday()
elif command == 'listholiday':
do_listholiday()
else:
print('命令使用方法:')
print("\tpython %s COMMAND [PARAMS] " % programName)
print("\tpython %s info FILEPATH [YYYY-MM] " % programName)
print("\tpython %s addholiday YYYY-MM-DD TYPE(w:上班 h:休息)] " % programName)
print("\tpython %s listholiday " % programName)
- END -
本文为原创文章
❤:在这里跟我一起学习技术、职场、人生、原理、健身、摄影、生活等知识吧!
❤: 欢迎点个关注一起学习,进步充实人生。