如何提高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实现用户登陆邮件通知的方法
Jul 09 Python
matplotlib绘制符合论文要求的图片实例(必看篇)
Jun 02 Python
opencv改变imshow窗口大小,窗口位置的方法
Apr 02 Python
使用python爬取B站千万级数据
Jun 08 Python
使用python批量读取word文档并整理关键信息到excel表格的实例
Nov 07 Python
Python requests模块实例用法
Feb 11 Python
Python倒排索引之查找包含某主题或单词的文件
Nov 13 Python
Pytorch实现各种2d卷积示例
Dec 30 Python
python tqdm 实现滚动条不上下滚动代码(保持一行内滚动)
Feb 19 Python
解决pyecharts运行后产生的html文件用浏览器打开空白
Mar 11 Python
Python网络爬虫四大选择器用法原理总结
Jun 01 Python
Python NumPy灰度图像的压缩原理讲解
Aug 04 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
删除html标签得到纯文本可处理嵌套的标签
2014/04/28 PHP
php计算年龄精准到年月日
2015/11/17 PHP
php基于dom实现读取图书xml格式数据的方法
2017/02/03 PHP
thinkphp5.1框架中容器(Container)和门面(Facade)的实现方法分析
2019/08/05 PHP
Laravel Eloquent ORM 实现查询表中指定的字段
2019/10/17 PHP
DIV菜单层实现代码
2010/11/19 Javascript
jQuery筛选器children()案例详解(图文)
2013/02/17 Javascript
jQuery 遍历-nextUntil()方法以及prevUntil()方法的使用介绍
2013/04/26 Javascript
图片Slider 带左右按钮的js示例
2013/08/30 Javascript
JavaScript中for循环的使用详解
2015/06/03 Javascript
javascript实现textarea中tab键的缩排处理方法
2015/06/26 Javascript
jQuery技巧之让任何组件都支持类似DOM的事件管理
2016/04/05 Javascript
基于JavaScript Array数组方法(新手必看篇)
2016/08/20 Javascript
如何使用 vue + d3 画一棵树
2018/12/03 Javascript
详解Vue用cmd创建项目
2019/02/12 Javascript
javascript实现5秒倒计时并跳转功能
2019/06/20 Javascript
关于JavaScript数组去重的一些理解汇总
2020/09/10 Javascript
Python判断值是否在list或set中的性能对比分析
2016/04/16 Python
解决Python 遍历字典时删除元素报异常的问题
2016/09/11 Python
Python使用Scrapy爬虫框架全站爬取图片并保存本地的实现代码
2018/03/04 Python
Python实现判断一行代码是否为注释的方法
2018/05/23 Python
matplotlib.pyplot绘图显示控制方法
2019/01/15 Python
Django框架自定义session处理操作示例
2019/05/27 Python
详解Python是如何实现issubclass的
2019/07/24 Python
python3图片文件批量重命名处理
2019/10/31 Python
Python遍历字典方式就实例详解
2019/12/28 Python
HTML5标签使用方法详解
2015/11/27 HTML / CSS
乌克兰香水和化妆品网站:Notino.ua
2018/03/26 全球购物
YSL圣罗兰美妆英国官网:Yves Saint Laurent Beauty UK
2019/08/03 全球购物
Linux常见面试题
2016/10/04 面试题
介绍一下如何优化MySql
2016/12/20 面试题
JPA的优势都有哪些
2013/07/04 面试题
夫妻忠诚协议范文
2014/11/16 职场文书
给老婆的保证书怎么写
2015/05/08 职场文书
写一个Python脚本下载哔哩哔哩舞蹈区的所有视频
2021/05/31 Python
Python Django ORM连表正反操作技巧
2021/06/13 Python