V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
p1094358629
V2EX  ›  Python

Python 怎么获取多线程的总执行时间??

  •  
  •   p1094358629 · 2020-06-22 14:50:05 +08:00 · 3114 次点击
    这是一个创建于 1640 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一个 多线程爬视频的 py 脚本,我想看下总的执行时间,求大佬帮忙看看???

    
    # -*- coding: utf-8 -*-
    # @Author : 徐燚敏
    # @File : movie_multiple.py
    # @Project: python_spider
    # @CreateTime : 2020-06-22 10
    # encoding utf-8
    import requests
    from queue import Queue
    import threading
    import time
    
    start_total_time = 0
    end_total_time = 0
    # 创建线程 生产者负责获取 URL,并且解析 URL
    class Procuder(threading.Thread):
    
        def __init__(self, num_queue, ts_queue, *args, **kwargs):
            super(Procuder, self).__init__(*args, **kwargs)
            self.num_queue = num_queue
            self.ts_queue = ts_queue
    
        def run(self):
            while True:
                if self.num_queue.empty():
                    # 如果队列为空就,线程执行完成,跳出死循环,结束 run
                    print("Procuder 队列为空")
                    break
                url = self.num_queue.get()
                self.download_ts(url)
    
        def download_ts(self, url):
            r = requests.get(url)
            ret = r.content
            # 倒数 8 位,取到文件名
            filename = url[-8:]
            self.ts_queue.put((ret, filename))
    
    
    # 创建线程 消费者 负责下载
    class Consumer(threading.Thread):
    
        def __init__(self, num_queue, ts_queue, *args, **kwargs):
            super(Consumer, self).__init__(*args, **kwargs)
            self.num_queue = num_queue
            self.ts_queue = ts_queue
    
        def run(self):
            while True:
                if self.ts_queue.empty() and self.num_queue.empty():
                    # 如果队列为空就,线程执行完成,跳出死循环,结束 run
                    print("Consumer 队列为空")
                    end_total_time = time.time()
                    break
                start_time = time.time()
                ret, filename = self.ts_queue.get()
                # 将 ts 文件保存到文件夹里
                with open('./mp4/{}'.format(filename), 'wb') as f:
                    f.write(ret)
                end_time = time.time()
                print('{}下载完成!,耗时:{}'.format(filename,end_time - start_time) )
    
    
    def main():
    
        # 定义线程
        num_queue = Queue(500)
        ts_queue = Queue(500)
        # 先自定义好总共爬取的数量
        # for i in range(470):
        for i in range(30):
            url = " https://us8.wl-cdn.com/hls/20200619/e1c5cc36967e6dac688b5e9c4006a567/film_" + '{0:05d}'.format(i) + ".ts"
            num_queue.put(url)
    
        # time.sleep(1)
        # 定义生产者
        for x in range(5):
            print("Procuder")
            t = Procuder(num_queue, ts_queue)
            t.start()
        # 定义消费者
        for x in range(5):
            print("Consumer")
            t = Consumer(num_queue, ts_queue)
            t.start()
    
    
    
    if __name__ == '__main__':
        start_total_time = time.time()
        lock = threading.RLock()
        # 加锁
        lock.acquire()
        try:
            main()
        finally:
            # 修改完成,释放锁
            lock.release()
            print("完成下载,总耗时{}".format(end_total_time - start_total_time))
            
            
    
    
    第 1 条附言  ·  2020-06-23 08:21:30 +08:00
    是我没表达清楚我的意思,先给大家说声抱歉,我想要的知道的时间:
    广义上就是我通过这个多线程脚本下载完这个视频一共要花的时间
    第 2 条附言  ·  2020-06-23 08:31:26 +08:00
    ```
    # Wait for all of them to finish
    for x in num_threads:
    x.join()
    for x in ts_threads:
    x.join()
    ```
    以上是解决方案
    13 条回复    2020-06-29 19:57:12 +08:00
    Aliencn
        1
    Aliencn  
       2020-06-22 15:21:08 +08:00
    调用 main 函数前后取时间戳,算差值不就行了
    johnsona
        2
    johnsona  
       2020-06-22 15:30:48 +08:00
    主线程等待子线程执行完再退出,守护线程
    marquina
        3
    marquina  
       2020-06-22 15:31:11 +08:00 via Android
    弄个字典,把每个线程的耗时放进去,完事后加起来
    lithbitren
        4
    lithbitren  
       2020-06-22 16:19:48 +08:00
    不明白难点在哪,希望知道总时间就直接测 main 的执行时间,需要知道各个线程的时间,就在重载的 run 函数首尾加上计时就行了,然后存字典存数组都可以直接存。io 密集的无所谓,如果 cpu 密集的最好给 run 函数传入一个进入线程的时间参数,不然有时候可能一开程就被挂起了,导致时间测量不太准确。

    不过这个循环也有点迷,如果判断 queue 不为空,判断完以后如果其他线程先把队列消费空了,那 get 方法就阻塞了啊。

    对于这种固定数量的任务,既然都用 requests 了,那直接上 grequests 就完事了,最多重写一下里面的方法加个成功的回调(原生库里面只有失败回调)。
    lithbitren
        5
    lithbitren  
       2020-06-22 16:33:00 +08:00
    requests 的 asyncio 版 requests-async 也可以,或者是 httpx 也行,不过要配好官方协程,最好把 py 的版本弄新一点,不然有时候可能会出现莫名其妙的 bug 。
    p1094358629
        6
    p1094358629  
    OP
       2020-06-22 20:10:11 +08:00
    @marquina 并行的哦,总和当然不对
    p1094358629
        7
    p1094358629  
    OP
       2020-06-22 20:10:29 +08:00
    @Aliencn 不对
    p1094358629
        8
    p1094358629  
    OP
       2020-06-22 20:11:53 +08:00
    @lithbitren 运行就直接 print 总时间了.
    jugelizi
        9
    jugelizi  
       2020-06-22 20:18:25 +08:00 via Android
    直接 print 最后一行就是结束时间 哈哈哈
    marquina
        10
    marquina  
       2020-06-22 20:36:21 +08:00
    @p1094358629 三个线程,线程 1 执行 3 秒,线程 2 执行 5 秒,线程 3 执行 4 秒,主线程等待三个线程结束。无非就两个执行时间,sum(3, 5, 4)、max(3, 5, 4)。先搞清楚你要的是哪个执行时间吧。
    momocraft
        11
    momocraft  
       2020-06-22 21:01:22 +08:00
    什么叫执行时间 实际在 cpu 跑的时间? 任务存在的时间?
    p1094358629
        12
    p1094358629  
    OP
       2020-06-23 08:24:39 +08:00
    @marquina 你说的也对,eg:我是把 100 个任务分发给 5 个进程去消费,我想知道的是广义上,执行最久的线程,也就是总的执行时间
    @marquina
    @momocraft
    nanfangzai
        13
    nanfangzai  
       2020-06-29 19:57:12 +08:00
    python 的多线程可以尝试下这个, 非常好用
    from concurrent.futures import ThreadPoolExecutor
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2707 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 15:30 · PVG 23:30 · LAX 07:30 · JFK 10:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.