2020软件工程第一次个人编程作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2020
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2020/homework/11167
这个作业的目标 制作一个程序完成对GitHub用户行为的统计与分析
学号 031802207
PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划
Estimate 估计这个任务需要多少时间 30 30
Development 开发
Analysis 需求分析 (包括学习新技术) 120 240
Design Spec 生成设计文档 60 60
Design Review 设计复审 60 60
Coding Standard 代码规范 (为目前的开发制定合适的规范) 30 30
Design 具体设计 60 60
Coding 具体编码 480 600
Code Review 代码复审 60 120
Test 测试(自我测试,修改代码,提交修改) 120 120
Reporting 报告
Test Report 测试报告 30 30
Size Measurement 计算工作量 30 30
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 120 120
合计 1200 1500
解题思路描述:
第一次个人编程作业就完完全全触及我的知识盲区,现在就是在课业繁重的同时还得学如何使用Git和GitHub、json,重拾不大咋会的Python(我爱数学建模,我爱操作系统,我爱数据库……)
大致思路:
首先从文件夹读入文档,其次对数据进行分析、统计,随后将处理完的数据按要求输出。
一开始看到示例代码就先扔到pycharm中运行,但是没有得到想要的结果(那是当然的怎么会这么简单呢?)
9月10日更新:
学习GitHub的使用教程,强忍着不去套机翻靠我六级飘过的水平把全英文的教学文档看了一遍。(还是不太懂,先做了再说)将助教的仓库fork到自己的仓库里。继续下一步。
9月12日更新:
参照廖雪峰老师的Git教程(https://www.liaoxuefeng.com/wiki/896043488029600 ) 以及菜鸟教程(https://www.runoob.com/git/git-tutorial.html ) 学习Git的安装配置和使用。
有关Git
Git常用有6个命令:git clone、git push、git add、git commit、git checkout、git pull
创建仓库命令
git init:初始化仓库
git clone:拷贝一份远程仓库,即下载一个项目

提交与修改
git add:添加文件到仓库
git status:查看仓库当前的状态,显示有变更的文件
git diff:比较文件的不同,即暂存区与工作区的差异
git commit:提交暂存区到本地仓库
git reset:回退版本
git rm:删除工作区文件
git mv:移动或重命名工作区文件
提交日志
git log:查看历史提交记录
git blame:以列表形式查看制定文件的历史修改记录
远程操作
git remote:远程仓库操作
git fetch:从远程获取代码库
git pull:下载远程代码并合并
git push:上传远程代码并合并
9月15日更新:
果然DDL才是第一生产力,开始研究示例代码(重新捡起好久没写的Python),然而学了一下午还是没大看懂。转去研究了测试文件,发现格式是json格式,在Python中可以直接调用JSON库对json文件进行操作。
有关JSON
JSON是一种轻量级的数据交换格式,易于用户阅读和编写。本次实践中需要用到json.loads和json.dumps两个函数,json.dumps用于将Python对象编码成JSON字符串;而json.loads用于阶码JSON数据,返回Python字段的数据类型。

有关命令行参数解析
看着代码束手无策,后面向班里大佬请教发现需要命令行参数解析进行传参,附上学习网站(https://www.runoob.com/python/python-command-line-arguments.html )
然而用神奇的pycharm就可以直接从RUN中设置parameter插入路径来实现命令行参数解析,即-i path;其中值得注意的是,在插入路径的时候,需要对路径里的反斜杠进行转义,可以通过用正斜杠替换或者在每个反斜杠前再加一个反斜杠来实现转义。(下附截图)

设计实现过程:

代码说明:
添加命令行参数
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() 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
初始化
` 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):
    self.__4Events4PerP = {}
    self.__4Events4PerR = {}
    self.__4Events4PerPPerR = {}
    for root, dic, files in os.walk(dict_address):
        for f in files:
            if f[-5:] == '.json':
                json_list = []
                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)
                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)`

代码规范连接
https://github.com/Lostsoul-namespace/2020-personal-python/blob/master/codestyle.md

优化思路
python众所周知跑得慢,尤其单线程,跑大量数据就更慢,所以大致的优化思路应该是往多线程的方向优化,但是菜鸡并没有掌握多线程的写法,只能写下大致思路。
性能测试截图

这里的性能测试是通过pycharm里的profile直接生成)

总结
(数学建模老折磨人)
python从入门到入土
几天时间逼着自己学好多看不懂的东西,很多知识不是看看就会,尤其是计算机,
还是得理论结合实际才能出效果。
最后,希望之后的项目中自己能够不这么狼狈吧,不要再拿ddl是第一生产力当借口!!!

posted @ 2020-09-16 00:47  吐魂君  阅读(167)  评论(2编辑  收藏  举报