Python3如何使用多线程升程序运行速度


Posted in Python onAugust 11, 2020

优化前后新老代码如下:

from git_tools.git_tool import get_collect_projects, QQNews_Git
from threading import Thread, Lock
import datetime

base_url = "http://git.xx.com"
project_members_commits_lang_info = {}
lock = Lock()
threads = []

'''
Author:zenkilan
'''


def count_time(func):
  def took_up_time(*args, **kwargs):
    start_time = datetime.datetime.now()
    ret = func(*args, **kwargs)
    end_time = datetime.datetime.now()
    took_up_time = (end_time - start_time).total_seconds()
    print(f"{func.__name__} execution took up time:{took_up_time}")
    return ret

  return took_up_time


def get_project_member_lang_code_lines(git, member, begin_date, end_date):
  global project_members_commits_lang_info
  global lock
  member_name = member["username"]
  r = git.get_user_info(member_name)
  if not r["id"]:
    return
  user_commits_lang_info = git.get_commits_user_lang_diff_between(r["id"], begin_date, end_date)
  if len(user_commits_lang_info) == 0:
    return
  lock.acquire()
  project_members_commits_lang_info.setdefault(git.project, dict())
  project_members_commits_lang_info[git.project][member_name] = user_commits_lang_info
  lock.release()


def get_project_lang_code_lines(project, begin_date, end_date):
  global threads
  git = QQNews_Git(project[1], base_url, project[0])
  project_members = git.get_project_members()
  if len(project_members) == 0:
    return
  for member in project_members:
    thread = Thread(target=get_project_member_lang_code_lines, args=(git, member, begin_date, end_date))
    threads.append(thread)
    thread.start()


@count_time
def get_projects_lang_code_lines(begin_date, end_date):
  """
  获取项目代码行语言相关统计——新方法(提升效率)
  应用多线程替代for循环
  并发访问共享外部资源
  :return:
  """
  global project_members_commits_lang_info
  global threads
  for project in get_collect_projects():
    thread = Thread(target=get_project_lang_code_lines, args=(project, begin_date, end_date))
    threads.append(thread)
    thread.start()


@count_time
def get_projects_lang_code_lines_old(begin_date, end_date):
  """
  获取项目代码行语言相关统计——老方法(耗时严重)
  使用最基本的思路进行编程
  双层for循环嵌套并且每层都包含耗时操作
  :return:
  """
  project_members_commits_lang_info = {}
  for project in get_collect_projects():
    git = QQNews_Git(project[1], base_url, project[0])
    project_members = git.get_project_members()
    user_commits_lang_info_dict = {}
    if len(project_members) == 0:
      continue
    for member in project_members:
      member_name = member["username"]
      r = git.get_user_info(member_name, debug=False)
      if not r["id"]:
        continue
      try:
        user_commits_lang_info = git.get_commits_user_lang_diff_between(r["id"], begin_date, end_date)
        if len(user_commits_lang_info) == 0:
          continue
        user_commits_lang_info_dict[member_name] = user_commits_lang_info
        project_members_commits_lang_info[git.project] = user_commits_lang_info_dict
      except:
        pass
  return project_members_commits_lang_info


def test_results_equal(resultA, resultB):
  """
  测试方法
  :param resultA:
  :param resultB:
  :return:
  """
  print(resultA)
  print(resultB)
  assert len(str(resultA)) == len(str(resultB))


if __name__ == '__main__':
  from git_tools.config import begin_date, end_date

  get_projects_lang_code_lines(begin_date, end_date)
  for t in threads:
    t.join()
  old_result = get_projects_lang_code_lines_old(begin_date, end_date)
  test_results_equal(old_result, project_members_commits_lang_info)

老方法里外层for循环和内层for循环里均存在耗时操作:

1)git.get_project_members()

2)git.get_user_info(member_name, debug=False)

分两步来优化,先里后外或先外后里都行。用多线程替换for循环,并发共享外部资源,加锁避免写冲突。

测试结果通过,函数运行时间装饰器显示(单位秒):

get_projects_lang_code_lines execution took up time:1.85294

get_projects_lang_code_lines_old execution took up time:108.604177

速度提升了约58倍

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python线程的两种编程方式
Apr 14 Python
Python简单遍历字典及删除元素的方法
Sep 18 Python
Python3中条件控制、循环与函数的简易教程
Nov 21 Python
python实现百万答题自动百度搜索答案
Jan 16 Python
python中使用 xlwt 操作excel的常见方法与问题
Jan 13 Python
python定时复制远程文件夹中所有文件
Apr 30 Python
Python中py文件转换成exe可执行文件的方法
Jun 14 Python
django 自定义过滤器(filter)处理较为复杂的变量方法
Aug 12 Python
python爬虫增加访问量的方法
Aug 22 Python
Python模块相关知识点小结
Mar 09 Python
Python使用文件操作实现一个XX信息管理系统的示例
Jul 02 Python
Python return语句如何实现结果返回调用
Oct 15 Python
使用Python pip怎么升级pip
Aug 11 #Python
python中通过pip安装库文件时出现“EnvironmentError: [WinError 5] 拒绝访问”的问题及解决方案
Aug 11 #Python
Python 代码调试技巧示例代码
Aug 11 #Python
python+pygame实现坦克大战小游戏的示例代码(可以自定义子弹速度)
Aug 11 #Python
Python函数递归调用实现原理实例解析
Aug 11 #Python
零基础学python应该从哪里入手
Aug 11 #Python
Python如何测试stdout输出
Aug 10 #Python
You might like
PHP读取网页文件内容的实现代码(fopen,curl等)
2011/06/23 PHP
PHP及Zend Engine的线程安全模型分析
2011/11/10 PHP
PHP实现JS中escape与unescape的方法
2016/07/11 PHP
jQuery代码优化 事件委托篇
2011/11/01 Javascript
S2SH整合JQuery+Ajax实现登录验证功能实现代码
2013/01/30 Javascript
web css实现整站样式互相切换
2013/10/29 Javascript
JavaScript实现的使用键盘控制人物走动实例
2014/08/27 Javascript
Javascript学习笔记之函数篇(五) : 构造函数
2014/11/23 Javascript
javascript笛卡尔积算法实现方法
2015/04/08 Javascript
js操作数据库实现注册和登陆的简单实例
2016/05/26 Javascript
AngularJs定制样式插入到ueditor中的问题小结
2016/08/01 Javascript
JavaScript中省略元素对数组长度的影响
2016/10/26 Javascript
学习JavaScript图片预加载模块
2016/11/07 Javascript
nodejs爬虫遇到的乱码问题汇总
2017/04/07 NodeJs
Vuejs 页面的区域化与组件封装的实现
2017/09/11 Javascript
JS简单添加元素新节点的方法示例
2018/02/10 Javascript
微信小程序地图(map)组件点击(tap)获取经纬度的方法
2019/01/10 Javascript
vue-cli构建vue项目的步骤详解
2019/01/27 Javascript
Vue使用轮询定时发送请求代码
2020/08/10 Javascript
解决vue单页面应用进入页面加载所有 js 的问题
2020/08/12 Javascript
Python 爬虫学习笔记之多线程爬虫
2016/09/21 Python
python-itchat 获取微信群用户信息的实例
2019/02/21 Python
tensorflow2.0保存和恢复模型3种方法
2020/02/03 Python
python如何代码集体右移
2020/07/20 Python
Python之字典添加元素的几种方法
2020/09/30 Python
详解python中的异常和文件读写
2021/01/03 Python
Python列表元素删除和remove()方法详解
2021/01/04 Python
瑰珀翠美国官网:Crabtree & Evelyn美国
2016/11/29 全球购物
税务会计岗位职责
2014/02/18 职场文书
园林设计专业毕业生求职信
2014/03/23 职场文书
总经理人事任命书
2014/06/05 职场文书
行政求职信
2014/07/04 职场文书
2014年财务科工作总结
2014/11/11 职场文书
春秋淹城导游词
2015/02/11 职场文书
考生诚信考试承诺书(2016版)
2016/03/25 职场文书
java如何实现获取客户端ip地址的示例代码
2022/04/07 Java/Android