Python脚本长执行函数
Python script long execuation function
你好,我遇到了一个问题,我的脚本中的函数需要很长时间才能执行。所以我正在尝试优化代码,我目前正在为此使用 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
如果我只是 运行 你的脚本并检查两个主要调用的时间 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
你好,我遇到了一个问题,我的脚本中的函数需要很长时间才能执行。所以我正在尝试优化代码,我目前正在为此使用 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
如果我只是 运行 你的脚本并检查两个主要调用的时间 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