这个作业属于哪个课程 | https://edu.cnblogs.com/campus/fzu/SE2020/ |
---|---|
这个作业要求在哪里 | https://edu.cnblogs.com/campus/fzu/SE2020/homework/11167 |
这个作业的目标 | <进一步学习GitHub的使用,学会读写json文件并进行数据的统计与分析> |
学号 | <031801125> |
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 60 |
Estimate | 估计这个任务需要多少时间 | 900 | 1200+ |
Development | 开发 | 200 | |
Analysis | 需求分析 (包括学习新技术) | 240 | 360 |
Design Spec | 生成设计文档 | 90 | 90 |
Design Review | 设计复审 | 60 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 40 |
Design | 具体设计 | 100 | 180 |
Coding | 具体编码 | 240 | 240 |
Code Review | 代码复审 | 150 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 150 | 60 |
Reporting | 报告 | 60 | 60 |
Test Report | 测试报告 | 60 | 60 |
Size Measurement | 计算工作量 | 40 | 30 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 60 | 60 |
解题思路
刚看到题目的时候好懵,GH Archive是啥,四种信息类型是啥,GitHub Actions又是啥?怎么进行单元测试?fork的仓库里yml文件是啥?
既然这样,那就按题目的要求一步一步学叭!
- 首先根据题目中的前置要求,我下载了Git,并学习相关的Git命令,然后fork对应的文件。
- 接着我查看了题目所给的json文件,观察数据,发现已经列出了四种信息类型,对题目的理解瞬间就清晰了!我的第一想法是可以用遍历这种笨方法来进行数据的统计与分析。但是接着我产生了疑惑,就是怎么区别个人事件和项目事件?简单粗暴的遍历让内存爆掉可咋办?
- 那么我是用C++还是python嘞?在纠结了一分钟之后,我决定还是用python来解题,虽然之前只自学了一丁点,但这样就有动力学习python了hh。
- 那就先看看题目给的参考程序吧!
学习过程
- 首先我学习了GitHub的使用,然后通过逐行百度学习了题目给的参考程序,原来argparse是Python内置的一个用于命令项选项与参数解析的模块,它主要有三个步骤:创建
ArgumentParser()
对象、调用add_argument()
方法添加参数和使用parse_args()
解析添加的参数,这样就能大概理解下面代码中的思路啦。通过在python中引入json库,利用json.loads()
函数(将json格式数据转换为字典)和json.dump()
函数(将列表字典进行字符串化操作然后写入json文件)实现对json文件的读写是完成这道题的前提。
还有os.path.exists()
就是判断括号里的文件是否存在的意思,raise()
是引发异常的函数,update()
函数是将两个字典合并。 - 了解了什么是代码规范,如何制定代码规范。
遇到的问题
Q:运行python时出现no python interpreter configured for the project
A:pycharm->Settings->Project Interpreter->Add Local->New enviroment
Q:在写导入json的相关代码时,总是显示FileNotFoundError: [Errno 2] No such file or directory
A:经过再一次的百度,我明白了原来是我忘记使用绝对路径,maybe默认以程序所在的路径作为当前路径来查找,所以就会报错说找不到文件
Q:在pycharm的run里找不到profile
A:原来我下载的是社区版啊。。。
实现过程
代码说明
命令行参数设置
def initArgparse(self):
self.parser = argparse.ArgumentParser()
self.parser.add_argument('-i', '--init')
self.parser.add_argument('-u', '--user')
self.parser.add_argument('-r', '--repo')
self.parser.add_argument('-e', '--event')
读json文件
def __init__(self, dict_address: int = None, reload: int = 0):
if reload == 1:
self.__init(dict_address)
if dict_address is None and not os.path.exists('1.json') and not os.path.exists('2.json') and not os.path.exists('3.json'):
raise RuntimeError('error: init failed')
x = open('1.json', 'r', encoding='utf-8').read()
self.__4Events4PerP = json.loads(x)
x = open('2.json', 'r', encoding='utf-8').read()
self.__4Events4PerR = json.loads(x)
x = open('3.json', 'r', encoding='utf-8').read()
self.__4Events4PerPPerR = json.loads(x)
统计相关数据
def __init(self, dict_address: str):
json_list = []
for root, dic, files in os.walk(dict_address):
for f in files:
if f[-5:] == '.json':
json_path = f
x = open(dict_address+'\'+json_path,
'r', encoding='utf-8').read()
str_list = [_x for _x in x.split('
') if len(_x) > 0]
for i, _str in enumerate(str_list):
try:
json_list.append(json.loads(_str))
except:
pass
records = self.__listOfNestedDict2ListOfDict(json_list)
self.__4Events4PerP = {}
self.__4Events4PerR = {}
self.__4Events4PerPPerR = {}
for i in records:
if not self.__4Events4PerP.get(i['actor__login'], 0):
self.__4Events4PerP.update({i['actor__login']: {}})
self.__4Events4PerPPerR.update({i['actor__login']: {}})
self.__4Events4PerP[i['actor__login']][i['type']
] = self.__4Events4PerP[i['actor__login']].get(i['type'], 0)+1
if not self.__4Events4PerR.get(i['repo__name'], 0):
self.__4Events4PerR.update({i['repo__name']: {}})
self.__4Events4PerR[i['repo__name']][i['type']
] = self.__4Events4PerR[i['repo__name']].get(i['type'], 0)+1
if not self.__4Events4PerPPerR[i['actor__login']].get(i['repo__name'], 0):
self.__4Events4PerPPerR[i['actor__login']].update({i['repo__name']: {}})
self.__4Events4PerPPerR[i['actor__login']][i['repo__name']][i['type']
] = self.__4Events4PerPPerR[i['actor__login']][i['repo__name']].get(i['type'], 0)+1
生成新的json文件并查询
def_save_newjson
with open('1.json', 'w', encoding='utf-8') as f:
json.dump(self.__4Events4PerP,f)
with open('2.json', 'w', encoding='utf-8') as f:
json.dump(self.__4Events4PerR,f)
with open('3.json', 'w', encoding='utf-8') as f:
json.dump(self.__4Events4PerPPerR,f)
def __parseDict(self, d: dict, prefix: str):
_d = {}
for k in d.keys():
if str(type(d[k]))[-6:-2] == 'dict':
_d.update(self.__parseDict(d[k], k))
else:
_k = f'{prefix}__{k}' if prefix != '' else k
_d[_k] = d[k]
return _d
def __listOfNestedDict2ListOfDict(self, a: list):
records = []
for d in a:
_d = self.__parseDict(d, '')
records.append(_d)
return records
def getEventsUsers(self, username: str, event: str) -> int:
if not self.__4Events4PerP.get(username,0):
return 0
else:
return self.__4Events4PerP[username].get(event,0)
def getEventsRepos(self, reponame: str, event: str) -> int:
if not self.__4Events4PerR.get(reponame,0):
return 0
else:
return self.__4Events4PerR[reponame].get(event,0)
def getEventsUsersAndRepos(self, username: str, reponame: str, event: str) -> int:
if not self.__4Events4PerP.get(username,0):
return 0
elif not self.__4Events4PerPPerR[username].get(reponame,0):
return 0
else:
return self.__4Events4PerPPerR[username][reponame].get(event,0)
单元测试截图及描述
代码规范
https://github.com/oorangeH/2020-personal-python/blob/master/codestyle.md
小结
- CSDN真是个好东西
- 精通一门语言太重要了,否则只有思路不会敲代码就很绝望
- 以后要好好学python,多多练习,提高自己的编程能力
- 通过这次作业,我学到了很多东西,那种面对软工作业的无力感深刻我心,以后真的要好好学习了
- 不管现在自己多菜,都不能有抵触心理,一定要微笑着对待接下来的每一次软工作业,哪怕熬夜爆肝都要往前走啊