如何提高python 中for循环的效率


Posted in Python onApril 15, 2020

对于某个城市的出租车数据,一天就有33210000条记录,如何将每辆车的数据单独拎出来放到一个专属的文件中呢?

思路很简单:

就是循环33210000条记录,将每辆车的数据搬运到它该去的文件中。

但是对于3000多万条数据,一个一个循环太消耗时间,我花了2个小时才搬运了60万数据,算算3000万我需要花费100个小时,也就需要4-5天。并且还需要保证这五天全天开机,不能出现卡机的事故。

因此,需要使用并行进行for循环的技巧:

由于3000万数据放到csv中导致csv打不开,因此我就把一个csv通过split软件将其切分成每份60万,共53个csv。

我原来的思路是读取文件夹,获取由每一个60万的csv文件组成的列表,再分别对每一个60万的csv进行处理。实质上还是循环33210000次,并行for循环就是同时处理几个60万的csv文件,就能成倍的减少时间消耗。

并行进行for循环是受下面的方法启发:

我之前的做法类似这样:

words = ['apple', 'bananan', 'cake', 'dumpling']
  for word in words:
    print word

并行for循环类似这样:

from multiprocessing.dummy import Pool as ThreadPool
items = list()
pool = ThreadPool()
pool.map(process, items)
pool.close()
pool.join()

其中,process是进行处理的函数

实例代码如下:

# -*- coding: utf-8 -*-
import time
from multiprocessing.dummy import Pool as ThreadPool
def process(item):
  print('正在并行for循环')
  print(item)
  time.sleep(5)
items = ['apple', 'bananan', 'cake', 'dumpling']
pool = ThreadPool()
pool.map(process, items)
pool.close()
pool.join()

补充知识:Python3用多线程替代for循环提升程序运行速度

优化前后新老代码如下:

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 中for循环的效率就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现问号表达式(?)的方法
Nov 27 Python
python显示天气预报
Mar 02 Python
python处理csv数据的方法
Mar 11 Python
python僵尸进程产生的原因
Jul 21 Python
Python实现的redis分布式锁功能示例
May 29 Python
python实现简单图片物体标注工具
Mar 18 Python
pyqt5中QThread在使用时出现重复emit的实例
Jun 21 Python
关于ResNeXt网络的pytorch实现
Jan 14 Python
Python爬虫后获取重定向url的两种方法
Jan 19 Python
Python打包exe时各种异常处理方案总结
May 18 Python
python 实现图片特效处理
Apr 03 Python
Python进程池与进程锁之语法学习
Apr 11 Python
ipython jupyter notebook中显示图像和数学公式实例
Apr 15 #Python
解决 jupyter notebook 回车换两行问题
Apr 15 #Python
Python使用monkey.patch_all()解决协程阻塞问题
Apr 15 #Python
使用python处理题库表格并转化为word形式的实现
Apr 14 #Python
浅谈Python中re.match()和re.search()的使用及区别
Apr 14 #Python
Jupyter加载文件的实现方法
Apr 14 #Python
利用jupyter网页版本进行python函数查询方式
Apr 14 #Python
You might like
PHP curl模拟浏览器采集阿里巴巴的实现代码
2011/04/20 PHP
PHP+Mysql+jQuery查询和列表框选择操作实例讲解
2015/10/22 PHP
thinkPHP5.0框架整体架构总览【应用,模块,MVC,驱动,行为,命名空间等】
2017/03/25 PHP
PHP简单计算两个时间差的方法示例
2017/06/20 PHP
Thinkphp结合AJAX长轮询实现PC与APP推送详解
2017/07/31 PHP
php使用redis的有序集合zset实现延迟队列应用示例
2020/02/20 PHP
IE 条件注释详解总结(附实例代码)
2009/08/29 Javascript
js两行代码按指定格式输出日期时间
2011/10/21 Javascript
把jquery 的dialog和ztree结合实现步骤
2013/08/02 Javascript
用html+css+js实现的一个简单的图片切换特效
2014/05/28 Javascript
JS生成随机字符串的多种方法
2014/06/10 Javascript
ajaxFileUpload.js插件支持多文件上传的方法
2014/09/02 Javascript
javascript框架设计读书笔记之种子模块
2014/12/02 Javascript
node.js中的buffer.slice方法使用说明
2014/12/10 Javascript
原生javascript实现DIV拖拽并计算重复面积
2015/01/02 Javascript
js获取客户端操作系统类型的方法【测试可用】
2016/05/27 Javascript
js实现上下左右弹框划出效果
2017/03/08 Javascript
微信小程序 MD5的方法详解及实例代码
2017/03/10 Javascript
Bootstrap 表单验证formValidation 实现表单动态验证功能
2017/05/17 Javascript
Angular实现响应式表单
2017/08/04 Javascript
js blob类型url的视频下载问题的解决
2019/11/29 Javascript
vue ssr+koa2构建服务端渲染的示例代码
2020/03/23 Javascript
[39:08]完美世界DOTA2联赛PWL S3 LBZS vs CPG 第一场 12.12
2020/12/16 DOTA
python编程-将Python程序转化为可执行程序[整理]
2007/04/09 Python
python实现大文本文件分割
2019/07/22 Python
numpy 返回函数的上三角矩阵实例
2019/11/25 Python
关于Python字符串显示u...的解决方式
2020/03/06 Python
Python如何使用PIL Image制作GIF图片
2020/05/16 Python
python实现126邮箱发送邮件
2020/05/20 Python
Django Session和Cookie分别实现记住用户登录状态操作
2020/07/02 Python
python爬虫beautifulsoup解析html方法
2020/12/07 Python
美国领先的商务贺卡出版商:The Gallery Collection
2018/02/13 全球购物
eharmony澳大利亚:网上约会服务
2020/02/29 全球购物
测试驱动开发的主要步骤是什么
2014/12/10 面试题
县政府领导班子“四风”方面突出问题整改措施
2014/09/23 职场文书
假期读书倡议书3篇
2019/08/19 职场文书