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倍

转载于:https://www.cnblogs.com/LanTianYou/p/11498525.html

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python中可以使用多线程来加速for循环,特别是对于I/O密集型任务,如文件读写和网络请求,可以大大提升效率。具体实现可以使用Python内置的`threading`模块,以下是一个简单的示例代码: ```python import threading def worker(start, end): for i in range(start, end): # 这里是需要执行的任务 def multi_threading(): threads = [] start, end, interval = 0, 1000000, 10000 for i in range(start, end, interval): t = threading.Thread(target=worker, args=(i, i+interval)) threads.append(t) t.start() for t in threads: t.join() if __name__ == '__main__': multi_threading() ``` 上述代码中,我们定义了一个`worker`函数,它接收两个参数`start`和`end`,用于指定需要处理的数据范围。然后,在`multi_threading`函数中,我们启动多个线程,每个线程处理一段数据范围。最后,我们等待所有线程执行完毕。 需要注意的是,多线程并不总是能够提升效率,如果任务本身是计算密集型,那么多线程反而可能会降低效率,因为线程之间的切换也需要时间。此时,可以考虑使用多进程来实现并行计算。 ### 回答2: 在Python中,使用多线程可以加速处理for循环速度多线程是指同时运行多个线程,每个线程独立执行任务。在for循环中,可以将循环中的每个任务分配给不同的线程来并行处理,从而加快整个循环的执行速度。 使用多线程加速for循环的主要步骤如下: 1. 导入threading库,它是Python中用于创建和管理线程的标准库。 2. 定义一个线程函数,该函数包含for循环中需要执行的任务。这个函数会在每个线程中调用。 3. 创建多个线程对象,并将线程函数和需要处理的数据作为参数传递给线程对象。 4. 启动每个线程,使其开始执行任务。 5. 等待所有线程完成任务,可以使用join()方法来实现。 需要注意的是,在使用多线程加速for循环时,要注意线程间的同步和资源竞争问题。可以使用锁或其他同步机制来确保线程安全。 总的来说,使用多线程可以将for循环中的任务分配给多个线程并行处理,从而加快整个循环速度。但在实际应用中,要注意线程安全和资源竞争的问题。 ### 回答3: Python中的多线程可以用于加速for循环的执行。在Python中,GIL(全局解释器锁)的存在会导致同一时间只有一个线程执行Python字节码。因此,多个线程同时执行CPU密集型的任务时,并不能真正实现并行计算,只能通过线程切换的方式来模拟并发执行。 然而,对于IO密集型的任务,多线程可以在一定程度上加速程序的执行。比如,当一个for循环中包含了多个IO操作(如网络请求、文件读写等),多个线程可以并行地执行这些IO操作,从而提高程序的整体执行效率。 在Python中,可以使用`threading`模块来创建和管理线程。首先,需要导入`threading`模块,然后通过继承`threading.Thread`类或者创建`threading.Thread`类的实例来创建线程。然后,可以将要执行的任务封装成一个函数,通过调用`start()`方法来启动线程,并通过调用`join()`方法来等待线程的完成。 以下是一个简单的示例代码,演示了如何使用多线程加速for循环的执行: ```python import threading def task(i): # 执行某个任务,比如网络请求等 print(f"线程{i}开始执行任务") # ... threads = [] for i in range(10): t = threading.Thread(target=task, args=(i,)) threads.append(t) t.start() for t in threads: t.join() ``` 在上述代码中,我们创建了10个线程,并通过循环将这些线程启动。每个线程执行`task`函数,并传入不同的参数。最后,我们通过循环调用`join`方法,等待所有线程的完成。 需要注意的是,在使用多线程加速for循环时,可能会遇到一些线程安全的问题,比如资源竞争、死锁等。为了避免这些问题,可以使用线程锁(`threading.Lock`)来保证同一时间只有一个线程访问某个共享资源。同时,需要注意尽量避免在多线程中修改共享的可变对象,以免引发意想不到的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值