软工第一次个人编程作业

这个作业属于哪个课程 软件工程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的使用上浪费了不少时间。今后要多主动课外自学,提高应对实际问题的能力。

posted @ 2020-09-14 22:56  Concorde  阅读(235)  评论(1编辑  收藏  举报