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局域网ip扫描示例分享
Apr 03 Python
使用Turtle画正螺旋线的方法
Sep 22 Python
django项目运行因中文而乱码报错的几种情况解决
Nov 07 Python
TensorFlow平台下Python实现神经网络
Mar 10 Python
python 获取当天每个准点时间戳的实例
May 22 Python
对python自动生成接口测试的示例讲解
Nov 30 Python
Python通过paramiko远程下载Linux服务器上的文件实例
Dec 27 Python
解决python线程卡死的问题
Feb 18 Python
python使用time、datetime返回工作日列表实例代码
May 09 Python
详解基于python-django框架的支付宝支付案例
Sep 23 Python
Python可变参数会自动填充前面的默认同名参数实例
Nov 18 Python
Python基于字典实现switch case函数调用
Jul 22 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
MySQL连接数超过限制的解决方法
2011/07/17 PHP
用PHP写的基于Memcache的Queue实现代码
2011/11/27 PHP
php生成zip压缩文件的方法详解
2013/06/09 PHP
PHP设计模式之调解者模式的深入解析
2013/06/13 PHP
php项目开发中用到的快速排序算法分析
2016/06/25 PHP
Redis使用Eval多个键值自增的操作实例
2016/11/04 PHP
浅谈PHP之ThinkPHP框架使用详解
2020/07/21 PHP
javascript间隔刷新的简单实例
2013/11/14 Javascript
Javascript实现简单的富文本编辑器附演示
2014/06/16 Javascript
javascript Deferred和递归次数限制实例
2014/10/21 Javascript
cookie的secure属性详解
2015/04/08 Javascript
js实现适用于素材网站的黑色多级菜单导航条效果
2015/08/24 Javascript
JS监听微信、支付宝等移动app及浏览器的返回、后退、上一页按钮的事件方法
2016/08/05 Javascript
JQuery实现文字无缝滚动效果示例代码(Marquee插件)
2017/03/07 Javascript
利用node.js写一个爬取知乎妹纸图的小爬虫
2017/05/03 Javascript
jQuery DOM节点的遍历方法小结
2017/08/15 jQuery
webpack 模块热替换原理
2018/04/09 Javascript
微信小程序获取位置展示地图并标注信息的实例代码
2019/09/01 Javascript
antd-日历组件,前后禁止选择,只能选中间一部分的实例
2020/10/29 Javascript
[01:02:54]完美世界DOTA2联赛PWL S2 FTD vs GXR 第一场 11.22
2020/11/26 DOTA
Python标准模块--ContextManager上下文管理器的具体用法
2017/11/27 Python
python中几种自动微分库解析
2019/08/29 Python
windows、linux下打包Python3程序详细方法
2020/03/17 Python
Python+MySQL随机试卷及答案生成程序的示例代码
2021/02/01 Python
卡骆驰新加坡官网:Crocs新加坡
2018/06/12 全球购物
俄罗斯在线手表和珠宝商店:AllTime
2019/09/28 全球购物
Street One瑞士:德国现代时装公司
2019/10/09 全球购物
理货员的岗位职责
2013/11/23 职场文书
行政人员岗位职责
2013/12/08 职场文书
法学专业自我鉴定
2014/02/05 职场文书
房产公证书范本
2014/04/10 职场文书
2014年禁毒工作总结
2014/11/24 职场文书
Redis安装启动及常见数据类型
2021/04/14 Redis
Django程序的优化技巧
2021/04/29 Python
Java多条件判断场景中规则执行器的设计
2021/06/26 Java/Android
netty 实现tomcat的示例代码
2022/06/05 Servers