Python常用脚本工具

工欲善其事,必先利其器。

Python常用脚本工具_第1张图片

脚本可解放劳动力,自觉学习一门脚本开发很是重要。以下是为工作过程中通过 Python 脚本减少手动工作量的场景以及工具实现代码。后续还会继续更新。

批量clone项目以及更新远程项目地址

场景:因为项目中用到了模块化开发(安卓),整个项目分成了十几个子模块,然后前端时间公司 git 要进行迁移,这么多模块手动一个个更新、切换分支以及更换远程地址肯定是很麻烦,使用脚本批量操作就是一件很方便的事,还可以将脚本分享给其他同事使用。当然 shell 脚本更容易,选择 python 主要是熟并且我司电脑均是自带 python 环境。比较废话,以下是为实现代码:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# 一键clone所有模块工程、批量修改仓库地址

# 使用说明:
# 1)配置 REPO_CONFIGS 包括项目路径,老仓库地址(可不进行配置),新仓库地址(注意配置项一一对应);
# 2)将本脚本放到项目同级目录下;
# 3)执行脚本:python git_repo.py ;
# 4) 也可用 shell 脚本,更方便。
# 5) python 2.7 或 3 均可使用。
# 6) 最好所有的模块都放在同一目录,不在同一目录,dir 配置则需使用相对或绝对路径。
# 7) 执行脚本前,先 stash 或 commit 当前分支修改。因为脚本会直接先切到 develop 进行操作。

import re
import os

# Python通过prettytable模块将输出内容如表格方式整齐输出,python本身并不内置,需要独立安装该第三方库。
from prettytable import PrettyTable

OLD_REPO = 'gitAddr:gitGroup/%s.git' # 这里修改为旧的 gitAddr 和 gitGroup 名
NEW_REPO = 'gitAddr:gitGroup/%s.git' # 这里修改为新的 gitAddr 和 gitGroup 名

PROJECT_DIRS = [
         'module1', 'module2', 'module3'
         ]                                 # 这里修改为自己的模块名列表

# 通过 prettytable 模块按表格样式输出内容。安装第三方库:pip3 install PrettyTable
def printProjectDir(projectDirs):
    x = PrettyTable(["olderRepo", "projectName", "newerRepo"])
    x.align["projectName"] = "1"
    x.padding_width = 1  # 填充宽度
    for projectDir in projectDirs:
        oldRepo = NAPOS_OLD_REPO % (projectDir)
        newRepo = NAPOS_NEW_REPO % (projectDir)
        x.add_row([oldRepo, projectDir, newRepo])
        # print(projectDir, oldRepo, newRepo)    

    print(x)    
    
def addNewBranch(branchName, projectDirs):
    for projectDir in projectDirs:
        existed = os.path.exists(projectDir)
        print(projectDir, existed)
        if (existed):
            os.chdir(projectDir)
            executeCmd('git checkout -b %s' % (branchName))
            executeCmd('git push origin %s' % (branchName))
            os.chdir('..')

def executeCmd(cmd):
    return os.system(cmd) # 返回值为0,执行命令成功

# clone 所有模块项目
def batchCloneRepo(repoAddr, projectDirs):
    for projectDir in projectDirs:
        # 当前目录不存在才clone
        if (os.path.exists(projectDir)):
            print('%s project has existed !' % (projectDir))
        else:
            repo = repoAddr % (projectDir)
            clone_res = executeCmd('git clone ' + repo)
            if (clone_res != 0):
                print('%s clone failed !' % (projectDir))
            else:
                print('%s clone successed !' % (projectDir))                
            
# 批量修改所有模块仓库地址(适用于不同group下的仓库迁移,需配置dir, newRepo字典数据)
# def batchSetRemoteUrl(configs):
#   for repoDict in configs:
#       setRemoteUrl(repoDict['dir'], repoDict['newRepo'])

# 批量更新所有模块 develop 分支代码
def batchFetch(repoAddr, projectDirs):
    for projectDir in projectDirs:
        existed = os.path.exists(projectDir)
        # print(projectDir, existed)
        if (existed):
            newRepo = repoAddr % (projectDir) 
            print(newRepo)
            os.chdir(projectDir)
            executeCmd('git checkout develop')
            executeCmd('git fetch')
            executeCmd('git merge')
            executeCmd('git branch --set-upstream-to origin/develop develop')
            os.chdir('..')
        else:
            print('%s project not existed !' % (projectDir))


# 批量修改所有模块仓库地址(适用于属于同一个group下的仓库迁移,只需配置 NEW_GROUP)
def batchSetSameGroupRemoteUrl(repoAddr, projectDirs):
    for projectDir in projectDirs:
        existed = os.path.exists(projectDir)
        # print(projectDir, existed)
        if (existed):
            newRepo = repoAddr % (projectDir) 
            print(newRepo)
            setRemoteUrl(projectDir, newRepo)
        else:
            print('%s project not existed !' % (projectDir))

def setRemoteUrl(projectDir, newRepo):
    if (newRepo != ''):
        # 进入到指定目录,执行cd命令无法改变命令行当前目录
        os.chdir(projectDir)

        # 先暂存当前分支修改,再执行切分支等命令
        # 恢复暂存,切换到之前的分支,执行命名:
        # 1)git stash list 查看所有暂存;2)git stash apply stash@{pos} 运用第pos条暂存内容,pos为你之前暂存的内容。
        stash_res = executeCmd('git stash')
        if (stash_res != 0):
            print('%s stash failed !' % (projectDir))

        checkout_res = executeCmd('git checkout develop')
        if (checkout_res != 0):
            print('%s checkout develop failed !' % (projectDir))

        executeCmd('git remote remove origin')
        executeCmd('git remote add origin %s' % (newRepo))
        # 查看远程仓库地址
        # executeCmd('git remote -v')
    
        executeCmd('git fetch')
        upstream_res = executeCmd('git branch --set-upstream-to origin/develop develop')
        if (upstream_res != 0):
            print('%s set-upstream failed !' % (projectDir))
        #  回到上级目录
        os.chdir('..')  

def printRemoteUrl(projectDirs):
    for projectDir in projectDirs:
        existed = os.path.exists(projectDir)
        if (existed):
            os.chdir(projectDir)
            executeCmd('git remote -v')
            os.chdir('..')

if __name__ == '__main__':
    # 批量克隆项目
    # batchCloneRepo(REPO_ADDR, PROJECT_DIRS)

    # 拉老版本的功能代码
    # batchFetch(OLD_REPO, PROJECT_DIRS)

    # 设置老远程仓库地址
    # batchSetSameGroupRemoteUrl(NEW_REPO, MY_DIRS)
    
    # 设置新仓库地址
    # batchSetSameGroupRemoteUrl(NEW_REPO, PROJECT_DIRS)

    # addNewBranch('testBranch', MY_DIRS)

    # 打印远程仓库地址
    # printRemoteUrl(PROJECT_DIRS)

    batchSetSameGroupRemoteUrl(repo, dirs)
查找某个目录下给定的后缀名文件名
#!/usr/bin/python
# -*- coding: UTF-8 -*-

import re
import os

def findFileNamesWithSuffix(myDir, suffix):
    os.chdir(myDir)
    arr = [x for x in os.listdir(myDir) if os.path.isfile(x) 
            and os.path.splitext(x)[1] == suffix]
    new_arr = []        
    for filename in arr:
        name = os.path.splitext(filename)
        new_arr.append(name[0])

    print(new_arr)      

findFileNamesWithSuffix('.', '.podSpec')
筛选json文件中多余键值

场景:一般随着迭代的更新换代,后台肯定保留了很多冗余字段或者兼容字段当前版本没有用到,若后台返回的json串过大,而客户端并不需要这么多字段,造成多余的Json解析时间,有些不好了。以下是为以客户端用到的对象字段生成的 json 串和后台返回的大 json 串对比,筛选出后台多余的字段。

# encoding:utf-8

import json

def readFile(file_path):
    f = open(file_path, 'r')
    content = f.read()
    f.close()
    return content

def readJsonFromFile(filename):
      jsonStr = readFile(filename)   
      return json.loads(jsonStr) 

def excludeAFromB(list_a, list_b):    
    return list(set(list_b).difference(set(list_a)))  # b中有而a中没有的

def excludeDictAFromB(dict_a, dict_b):
    a_keys = list(dict_a.keys())
    b_keys = list(dict_b.keys())    
    return list(set(b_keys).difference(set(a_keys)))  # b中有而a中没有的

def unionList(list_a, list_b):
    return list(set(list_a).union(set(list_b)))

def unionDictKeys(dict_a, dict_b, dict_c):
    a_keys = list(dict_a.keys())
    b_keys = list(dict_b.keys())
    c_keys = list(dict_c.keys())
    return unionList(a_keys, unionList(b_keys, c_keys))
        
def getResult():
    s_json = readJsonFromFile('./server.json')  # 同级目录服务端json文件
    a_json = readJsonFromFile('./android.json') # 同级目录安卓本地json文件
    # i_json = readJsonFromFile('./ios.json')
    # p_json = readJsonFromFile('./pc.json')

    # 求服务器中存在各段不存在的字段
    s_exc_a = excludeDictAFromB(a_json, s_json)
    # s_exc_i = excludeDictAFromB(i_json, s_json)
    # s_exc_p = excludeDictAFromB(p_json, s_json)
    print('server exclude android: ', s_exc_a)
    # print('server exclude ios: ', s_exc_i)
    # print('server exclude pc: ', s_exc_p)

    # 方案二:取三段使用字段取并集对比,缩小范围 
    # # 1. 求三段本地json数据并集
    # union_list = unionDictKeys(a_json, i_json, p_json)
    # print('Union client datas: ', union_list)
    # # 2. 从server json串中排除三端并集数据,为服务器参考字段
    # exclude_list = excludeAFromB(union_list, s_json.keys())
    # print('Server datas: ', exclude_list)

    output = open('./diff.txt', 'w')
    for data in s_exc_a:
        print(data)
        output.write(data + '\n')

getResult()

未完待续。

你可能感兴趣的:(Python常用脚本工具)