orange897

导航

软件工程实践个人编程作业

这个作业属于哪个课程 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文件是啥?
既然这样,那就按题目的要求一步一步学叭!

  1. 首先根据题目中的前置要求,我下载了Git,并学习相关的Git命令,然后fork对应的文件。
  2. 接着我查看了题目所给的json文件,观察数据,发现已经列出了四种信息类型,对题目的理解瞬间就清晰了!我的第一想法是可以用遍历这种笨方法来进行数据的统计与分析。但是接着我产生了疑惑,就是怎么区别个人事件和项目事件?简单粗暴的遍历让内存爆掉可咋办?
  3. 那么我是用C++还是python嘞?在纠结了一分钟之后,我决定还是用python来解题,虽然之前只自学了一丁点,但这样就有动力学习python了hh。
  4. 那就先看看题目给的参考程序吧!

学习过程

  1. 首先我学习了GitHub的使用,然后通过逐行百度学习了题目给的参考程序,原来argparse是Python内置的一个用于命令项选项与参数解析的模块,它主要有三个步骤:创建 ArgumentParser() 对象、调用 add_argument() 方法添加参数和使用 parse_args() 解析添加的参数,这样就能大概理解下面代码中的思路啦。通过在python中引入json库,利用json.loads()函数(将json格式数据转换为字典)和json.dump()函数(将列表字典进行字符串化操作然后写入json文件)实现对json文件的读写是完成这道题的前提。
    还有os.path.exists()就是判断括号里的文件是否存在的意思,raise()是引发异常的函数,update()函数是将两个字典合并。
  2. 了解了什么是代码规范,如何制定代码规范。

遇到的问题

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('\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

生成新的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,多多练习,提高自己的编程能力
  • 通过这次作业,我学到了很多东西,那种面对软工作业的无力感深刻我心,以后真的要好好学习了
  • 不管现在自己多菜,都不能有抵触心理,一定要微笑着对待接下来的每一次软工作业,哪怕熬夜爆肝都要往前走啊

posted on 2020-09-17 20:11  orange897  阅读(127)  评论(1编辑  收藏  举报