如何提高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中theano库的线性回归
Aug 31 Python
selenium3+python3环境搭建教程图解
Dec 07 Python
对python中的float除法和整除法的实例详解
Jul 20 Python
Django实现文件上传下载功能
Oct 06 Python
Python高级编程之继承问题详解(super与mro)
Nov 19 Python
python日期与时间戳的各种转换示例
Feb 12 Python
python GUI库图形界面开发之PyQt5控件QTableWidget详细使用方法与属性
Feb 25 Python
在python中使用pymysql往mysql数据库中插入(insert)数据实例
Mar 02 Python
python实现批量命名照片
Jun 18 Python
Python Request类源码实现方法及原理解析
Aug 17 Python
Python解析m3u8拼接下载mp4视频文件的示例代码
Mar 03 Python
总结Python使用过程中的bug
Jun 18 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获取数组中某元素的位置及array_keys函数应用
2013/01/29 PHP
php设置编码格式的方法
2013/03/05 PHP
PHP中执行MYSQL事务解决数据写入不完整等情况
2014/01/07 PHP
php生成二维码
2015/08/10 PHP
PHP实现的浏览器检查类
2016/04/11 PHP
Javascript常用运算符(Operators)-javascript基础教程
2007/12/14 Javascript
JQuery Tips(4) 一些关于提高JQuery性能的Tips
2009/12/19 Javascript
兼容ie、firefox的图片自动缩放的css跟js代码分享
2012/01/21 Javascript
异步动态加载js与css文件的js代码
2013/09/15 Javascript
jquery心形点赞关注效果的简单实现
2016/11/14 Javascript
Bootstrap中定制LESS-颜色及导航条(推荐)
2016/11/21 Javascript
js实现固定宽高滑动轮播图效果
2017/01/13 Javascript
浅谈regExp的test方法取得的值变化的原因及处理方法
2017/03/01 Javascript
Vue-Cli中自定义过滤器的实现代码
2017/08/12 Javascript
Node.js 使用递归实现遍历文件夹中所有文件
2017/09/18 Javascript
JavaScript for循环 if判断语句(学习笔记)
2017/10/11 Javascript
基于JavaScript实现表格滚动分页
2017/11/22 Javascript
Vue CLI 3.x 自动部署项目至服务器的方法
2019/04/02 Javascript
微信小程序非跳转式组件授权登录的方法示例
2019/05/22 Javascript
Python比较两个图片相似度的方法
2015/03/13 Python
初学Python函数的笔记整理
2015/04/07 Python
Python 实现简单的电话本功能
2015/08/09 Python
动感网页相册 python编写简单文件夹内图片浏览工具
2016/08/17 Python
Python实现将数据库一键导出为Excel表格的实例
2016/12/30 Python
Python实现判断一个字符串是否包含子串的方法总结
2017/11/21 Python
详解python使用pip安装第三方库(工具包)速度慢、超时、失败的解决方案
2018/12/02 Python
python进阶之自定义可迭代的类
2019/08/20 Python
CSS3制作缩略图的详细过程
2016/07/08 HTML / CSS
html5拖曳操作 HTML5实现网页元素的拖放操作
2013/01/02 HTML / CSS
5.1手机促销活动
2014/01/17 职场文书
咖啡店自主创业商业计划书
2014/01/22 职场文书
内勤主管岗位职责
2014/04/03 职场文书
小学优秀班干部事迹材料
2014/05/25 职场文书
创先争优个人承诺书
2014/08/30 职场文书
总经理司机岗位职责
2015/04/10 职场文书
分析SQL窗口函数之聚合窗口函数
2022/04/21 Oracle