软工第一次个人编程作业
这个作业属于哪个课程 | 软件工程2020秋学期 |
---|---|
这个作业要求在哪里 | [https://edu.cnblogs.com/campus/fzu/SE2020/homework/11167] |
这个作业的目标 | 学习利用程序解析大量的数据,并从中提取想要获取的信息。学习对json文件进行解析。熟悉GitHub的各项功能及代码编写的规范,养成良好的编程习惯。 |
学号 | 031802224 |
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 70 |
Estimate | 估计这个任务需要多少时间 | 100 | 150 |
Development | 开发 | 150 | 180 |
Analysis | 需求分析 (包括学习新技术) | 240 | 420 |
Design Spec | 生成设计文档 | 25 | 30 |
Design Review | 设计复审 | 30 | 80 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 20 |
Design | 具体设计 | 50 | 80 |
Coding | 具体编码 | ||
Code Review | 代码复审 | 50 | 120 |
Test | 测试(自我测试,修改代码,提交修改) | 120 | 120 |
Reporting | 报告 | 40 | 60 |
Test Report | 测试报告 | 10 | 20 |
Size Measurement | 计算工作量 | 10 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 40 | 60 |
合计 | 935 | 1430 |
解题思路描述。即刚开始拿到题目后,如何思考,如何找资料的过程。
本次题目的要求是制作一个程序来解析json文件,统计和分析 GitHub 的用户行为数据。刚看到这个题目时就有些懵,因为之前学习Python基本都是做编程题,没有接触过这种比较大型的项目。通过研究老师的参考代码中用到了什么,并在舍友的指导下,对问题有了一个基本思路。题目要求我们解析一个大规模的json文件。由于是大规模,首先要把文件放到本地,即缓存,其次,为了防止爆内存,必须用readline()按行读取。
由于老师说会有多个json文件,因此需要读取文件夹,找出其中所有的json文件,并对其进行解析,因此需要编写一个查找json文件的函数,还需要编写一个解析json文件的函数,可将其放在前面的查找函数中进行调用,一边查找一边解析。大致思路有了,可是由于我的编程能力比较弱,实现起来有些困难,只能阅读老师的代码模板并在其基础上进行修改。
由于我Python还学得不是很深,结果阅读参考代码的过程中也给我带来了不小的困扰,其中许多函数的使用、类的定义等都看得我一脸懵逼(通过请教舍友和自己的学习,现在能基本理解了)。许多知识点都需要我从零开始学习。通过在百度、CSDN、博客园上四处流窜,我学习到了不少新技能和知识。由于需要对指定路径下的文件进行解析,要利用os库来操作和处理文件路径(os.walk()函数);解析文件时要查找关键词,我们用get()函数来查找某一元素;为了能一行一行读取json,需要用readline()函数来逐行读取文件。新知识比如json库的使用,像是用json.loads()、json.dumps()函数进行类型转换、用argparse库编写命令行参数、UTF-8编码。另外,由于之前几乎没有用过github,对于它的许多功能使用起来比较费劲。比如git的原理和使用,我就看了了好几篇教程博文,有的还是不理解,就去B站上看视频教程。
设计实现过程。设计包括代码如何组织,关键函数的流程图。
代码说明。展示出项目关键代码,并解释思路。
根据题目需要,解析json文件时需要一行一行读入,对代码模板进行修改。
import json
import os
import argparse
class Data:
def __init__(self, dict_address: str = None, reload: int = 0):#初始化函数
if reload == 1:
self.__init(dict_address)
path=dict_address+'\\1.json'
if dict_address is None and not os.path.exists(path) and not os.path.exists('2.json') and not os.path.exists('3.json'):
raise RuntimeError('error: init failed')
f=open(path, 'r', encoding='utf-8')
x = f.readline()
while x:
self.__4Events4PerP = json.loads(x)
print(self.__4Events4PerP)
x=f.readline()
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('\n') 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
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)
class Run:
def __init__(self):
self.parser = argparse.ArgumentParser()
self.data = None
self.argInit()
print(self.analyse())
def argInit(self):
self.parser.add_argument('-i', '--init')
self.parser.add_argument('-u', '--user')
self.parser.add_argument('-r', '--repo')
self.parser.add_argument('-e', '--event')
def analyse(self):
if self.parser.parse_args().init:
self.data = Data(self.parser.parse_args().init, 1)
return 0
else:
if self.data is None:
self.data = Data("D:\学习\软件工程")
if self.parser.parse_args().event:
if self.parser.parse_args().user:
if self.parser.parse_args().repo:
res = self.data.getEventsUsersAndRepos(
self.parser.parse_args().user, self.parser.parse_args().repo, self.parser.parse_args().event)
else:
res = self.data.getEventsUsers(
self.parser.parse_args().user, self.parser.parse_args().event)
elif self.parser.parse_args().repo:
res = self.data.getEventsRepos(
self.parser.parse_args().reop, self.parser.parse_args().event)
else:
raise RuntimeError('error: argument -l or -c are required')
else:
raise RuntimeError('error: argument -e is required')
return res
if __name__ == '__main__':
a = Run()
给出你的代码规范的链接,即你的仓库中的 codestyle.md。
[https://github.com/Concorde999/2020-personal-python/blob/master/codestyle.md]
总结本次作业。
经过这次作业,才明白自己在mooc上学的Python还远远不够。自己的学习方式过于局限了,仅仅停留在做做简单的编程题,对于实际场景、大项目的应对能力还很不足,此外,此前对于GitHub的使用几乎是空白,导致这次在熟悉GitHub的使用上浪费了不少时间。今后要多主动课外自学,提高应对实际问题的能力。