【问题标题】:Python script long execuation functionPython脚本长执行函数
【发布时间】:2019-07-31 23:23:26
【问题描述】:

您好,我遇到了一个问题,我的脚本中的一个函数需要很长时间才能执行。所以我正在尝试优化代码,我目前正在为此使用 cProfile 和 Pstats。

当我执行一个函数时,大约需要 0.7 秒到 1+ 秒才能完成。在 Windows 上总是给出最长持续时间的项目是:

    Sun Mar 10 13:55:02 2019    profiles/getColors.profile

         657 function calls in 0.535 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
          1    0.714    0.714    0.714    0.714 {built-in method _winapi.WaitForMultipleObjects}_winapi.WaitForMultipleObjects}

在 Linux 上:

2    1.013    0.506    1.013    0.506 {built-in method posix.read}

所以我假设它必须对线程做一些事情,但我从不创建任何线程,而我的其他函数几乎不需要时间来完成,比如 ~0.1 秒,所以我的问题是为什么需要这么长时间是时候执行这段代码了:

def getColors(image, rows, columns, sectionedPixel):
# Flooring so we do not get decimal numbers
sectionColumns = math.floor(width / columns)
sectionRows = math.floor(height / rows)
colorValues = [0, 0, 0, 0]
leftRGBVal = [0, 0, 0]
rightRGBVal = [0, 0, 0]
topRGBVal = [0, 0, 0]
botRGBVal = [0, 0, 0]

# LEFT SIDE
getRiLeSideColor(image, 0, 10, leftRGBVal)
# RIGHT SIDE
getRiLeSideColor(image, width - 10, width, rightRGBVal)

# TOP SIDE
getToBoSideColor(image, 0, 10, topRGBVal)
# BOTTOM SIDE
getToBoSideColor(image, height - 10, height, botRGBVal)

colorValues[0] = leftRGBVal
colorValues[1] = rightRGBVal
colorValues[2] = topRGBVal
colorValues[3] = botRGBVal

return colorValues

CProfile 的完整日志: https://pastebin.com/jAA5FkPZ

完整代码: https://gist.github.com/Patrick265/592a7dccba4660a4e4210ddd5e9974eb

【问题讨论】:

    标签: python multithreading cprofile pstats


    【解决方案1】:

    如果我只是运行您的脚本并检查两个主要调用 retrieveScreen(...)getColors(...) 的时间,我会看到平均时间:

    retrieveScreen: 1.70369
    getColors:      0.07770
    

    我猜你的屏幕截图依赖于操作系统,只是需要时间。

    通过几个快速测试,我认为像这样获得屏幕的PixelAccess 应该更快,只使用裸PIL

    import PIL.ImageGrab
    
    pxlaccess = PIL.ImageGrab.grab().load()
    

    编辑:完整示例

    这个(python3)代码只使用PIL。老实说,我不确定枕头访问屏幕的实际方法,但它比你以前的方法略快。我认为您正在尝试实现屏幕背光之类的功能,这需要快速更新;不知道这是否足以满足您的目的。但是,请随意根据需要使用代码:

    #!/usr/bin/python3
    
    import time
    import PIL.ImageGrab
    
    
    def get_screen_and_dimensions():
        cap = PIL.ImageGrab.grab()
        return cap.load(), cap.size
    
    
    def average_color_from_rect(screen, x0, x1, y0, y1):
        color = [0, 0, 0]
        for x in range(x0, x1):
            for y in range(y0, y1):
                source = screen[x, y]
                for i in range(3):
                    color[i] += source[i]
        count = (x1 - x0) * (y1 - y0)
        return [round(color[i] / count) for i in range(3)]
    
    
    def main():
        t0 = time.time()
        screen, size = get_screen_and_dimensions()
        t1 = time.time()
        print(f'Grab screen: {t1 - t0:.4f}s')
    
        bandwidth = 10
        borders = {
            'top': (0, size[0], 0, bandwidth),
            'right': (size[0] - bandwidth, size[0], 0, size[1]),
            'bottom': (0, size[0], size[1] - bandwidth, size[1]),
            'left': (0, bandwidth, 0, size[1]),
        }
    
        t0 = time.time()
        for border, args in borders.items():
            color = average_color_from_rect(screen, *args)
            print(f'{border}: {color}')
        t1 = time.time()
        print(f'Color calculation: {t1 - t0:.4f}s')
    
    
    if __name__ == "__main__":
        main()
    

    示例输出,仅用于演示目的:

    $ python3 fiddle-colors.py 
    Grab screen: 0.3974s
    top: [35, 35, 35]
    right: [126, 126, 125]
    bottom: [134, 137, 139]
    left: [50, 50, 50]
    Color calculation: 0.0905s
    

    【讨论】:

    • 请问您使用的是什么操作系统?对于 Windows 和 Linux,我都得到了类似的输出。好吧,那么我需要重新考虑算法来获得屏幕的 RGB 值。谢谢!
    • 我在 macOS 上;查看编辑 - 该解决方案对我来说更快。
    猜你喜欢
    • 2019-09-23
    • 2018-08-29
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多