英文:
Function return value of wrong type if I use multiprocessing
问题
以下是您要翻译的代码部分:
import concurrent.futures
def get_data():
with concurrent.futures.ProcessPoolExecutor() as executor:
x = executor.submit(replace_elements, first(), elements_for_replace)
y = executor.submit(replace_elements, second(), elements_for_replace)
z = executor.submit(replace_elements, third(), elements_for_replace)
destroyAllWindows()
return x, y, z
在新版本的代码中,由于您使用了concurrent.futures
来并行执行函数,返回的变量是<class 'concurrent.futures._base.Future'>
而不是<class 'list'>
。要获取<class 'list'>
的返回值,您可以在executor.submit
后使用.result()
来获取结果。这是修改后的代码:
import concurrent.futures
def get_data():
with concurrent.futures.ProcessPoolExecutor() as executor:
x = executor.submit(replace_elements, first(), elements_for_replace)
y = executor.submit(replace_elements, second(), elements_for_replace)
z = executor.submit(replace_elements, third(), elements_for_replace)
destroyAllWindows()
return x.result(), y.result(), z.result()
这将确保get_data()
函数返回与第一个版本的代码相同的<class 'list'>
类型的结果。
英文:
world!
I have this code:
from numpy import array
from cv2 import imshow, cvtColor, imwrite, imread, destroyAllWindows, COLOR_BGR2RGB
from pyscreenshot import grab
import pytesseract
filename = 'image.png'
elements_for_replace = {'iL': '1L', 'Bi': 'B1', 'Bl': 'B1', 'Ci': 'C1', 'Cl': 'C1'}
pytesseract.pytesseract.tesseract_cmd = r'C:\Users\Administrator\AppData\Local\Tesseract-OCR\tesseract.exe'
def scanning(x1, y1, x2, y2):
screen = array(grab(bbox=(x1, y1, x2, y2)))
imwrite(filename, screen)
img = imread(filename)
text = pytesseract.image_to_string(img)
history = text.split()
return history
def first():
return scanning(730, 740, 1335, 790)
def second():
return scanning(730, 453, 1335, 500)
def third():
return scanning(817, 45, 1522, 99)
def replace_elements(data, replace_data):
for item in data:
if item in replace_data:
data[data.index(item)] = replace_data[item]
return data
def get_data():
x = replace_elements(first(), elements_for_replace)
y = replace_elements(second(), elements_for_replace)
z = replace_elements(third(), elements_for_replace)
destroyAllWindows()
return x, y, z
When the function get_data() is called, this code uses computer vision to translate an image into text at three different locations on the screen. Does it consistently. It then replaces the failed elements with the correct ones. At the output, we get a tuple of lists (x, y, z), which will be processed by another part of the program.
Converting images to text takes a lot of time. And the sequential execution of the program multiplies this time by 3. I came to the conclusion that I need to use the multiprocessing module (or rather concurrent.futures) to reduce the program execution time.
I rewrote the function get_data() like this:
import concurrent.futures
def get_data():
with concurrent.futures.ProcessPoolExecutor() as executor:
x = executor.submit(replace_elements, first(), elements_for_replace)
y = executor.submit(replace_elements, second(), elements_for_replace)
z = executor.submit(replace_elements, third(), elements_for_replace)
destroyAllWindows()
return x, y, z
Now the returned variables have data type <class 'concurrent.futures._base.Future'> instead of <class 'list'> and the program, trying to process this data, throws an error 'TypeError: 'Future' object is not subscriptable'.
How to start parallel execution of a function so that the return value of the function is the same as in the first version of the code, that is <class 'list'> ???
答案1
得分: 2
executor.submit()
返回一个 Future 对象,而不是被调用函数的值。为了获取函数返回的值,您必须在 Future 对象上调用 result()
。在您的情况下,您需要修改您的代码如下:
def get_data():
with concurrent.futures.ProcessPoolExecutor() as executor:
future_x = executor.submit(replace_elements, first(), elements_for_replace)
future_y = executor.submit(replace_elements, second(), elements_for_replace)
future_z = executor.submit(replace_elements, third(), elements_for_replace)
destroyAllWindows()
# 实际上获取函数的值
x = future_x.result()
y = future_y.result()
z = future_z.result()
return x, y, z
此外,作为建议,您还可以考虑使用 ProcessPoolExecutor.map()
来简化代码。使用它,您无需定义每个结果。
英文:
executor.submit()
returns a Future object, not the value of the function called. In order to get the value returned by the function, you must call result() on the Future object. In your case you'll want to modify your code like so:
def get_data():
with concurrent.futures.ProcessPoolExecutor() as executor:
future_x = executor.submit(replace_elements, first(), elements_for_replace)
future_y = executor.submit(replace_elements, second(), elements_for_replace)
future_z = executor.submit(replace_elements, third(), elements_for_replace)
destroyAllWindows()
# Actually get the value of the function here
x = future_x.result()
y = future_y.result()
z = future_z.result()
return x, y, z
Additionally, as a suggestion you could also look into using the ProcessPoolExecutor.map() to clean up the code a bit. With it, you wouldn't have to define each result.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论