如何提高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中内置的NotImplemented类型的用法
Mar 31 Python
Python采用Django制作简易的知乎日报API
Aug 03 Python
Python制作刷网页流量工具
Apr 23 Python
教你使用python画一朵花送女朋友
Mar 29 Python
django的登录注册系统的示例代码
May 14 Python
用Python实现读写锁的示例代码
Nov 05 Python
学习python分支结构
May 17 Python
python爬虫 urllib模块url编码处理详解
Aug 20 Python
Python continue语句实例用法
Feb 06 Python
Python 实现使用空值进行赋值 None
Mar 12 Python
基于Python和C++实现删除链表的节点
Jul 06 Python
Python使用cn2an实现中文数字与阿拉伯数字的相互转换
Mar 02 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 数据结构 算法 三元组 Triplet
2011/07/02 PHP
PHP实现的线索二叉树及二叉树遍历方法详解
2016/04/25 PHP
phpmailer简单发送邮件的方法(附phpmailer源码下载)
2016/06/13 PHP
Laravel中如何增加自定义全局函数详解
2017/05/09 PHP
JavaScript 节点操作 以及DOMDocument属性和方法
2007/12/06 Javascript
js 替换
2008/02/19 Javascript
prettify 代码高亮着色器google出品
2010/12/28 Javascript
javascript使用中为什么10..toString()正常而10.toString()出错呢
2013/01/11 Javascript
使用Post提交时须将空格转换成加号的解释
2013/01/14 Javascript
javascript自动给文本url地址增加链接的方法分享
2014/01/20 Javascript
javascript处理表单示例(javascript提交表单)
2014/04/28 Javascript
使用ajaxfileupload.js实现ajax上传文件php版
2014/06/26 Javascript
jQuery实现圣诞节礼物传送(花式轮播)
2016/12/25 Javascript
Layui table 组件的使用之初始化加载数据、数据刷新表格、传参数
2017/09/11 Javascript
详解vue-router 初始化时做了什么
2018/06/11 Javascript
微信小程序--获取用户地理位置名称(无须用户授权)的方法
2019/04/29 Javascript
js实现拖拽元素选择和删除
2020/08/25 Javascript
仿照Element-ui实现一个简易的$message方法
2020/09/14 Javascript
[01:28]一分钟告诉你DOTA2 TI9不朽宝藏Ⅱ中有什么!
2019/07/09 DOTA
python dict.get()和dict['key']的区别详解
2016/06/30 Python
python 异常处理总结
2016/10/18 Python
Python绑定方法与非绑定方法详解
2017/08/18 Python
将Python文件打包成.EXE可执行文件的方法
2019/08/11 Python
python+jinja2实现接口数据批量生成工具
2019/08/28 Python
Python数据处理篇之Sympy系列(五)---解方程
2019/10/12 Python
Python模块zipfile原理及使用方法详解
2020/08/04 Python
HTML5 Plus 实现手机APP拍照或相册选择图片上传功能
2016/07/13 HTML / CSS
美国知名的旅游网站:OneTravel
2018/10/09 全球购物
Feelunique澳大利亚:欧洲的化妆品零售电商
2019/12/18 全球购物
高中生自我评价个人范文
2013/11/09 职场文书
机械工程师的岗位职责
2013/11/17 职场文书
大专生的学习自我评价
2013/12/04 职场文书
幼儿园中秋节活动方案
2014/02/06 职场文书
客户经理岗位职责大全
2015/04/09 职场文书
2015年办公室人员工作总结
2015/05/15 职场文书
联村联户简报
2015/07/21 职场文书