Python Executor - Passando função com argumento como argumento

Aug 26 2020

Meu objetivo é criar uma função que possa usar para medir a execução e o uso de recursos de outra função. Usando um tutorial, criei o seguinte usando ThreadPoolExecutor do Python:

from resource import *
from time import sleep
from concurrent.futures import ThreadPoolExecutor

class MemoryMonitor:
    def __init__(self):
        self.keep_measuring = True

    def measure_usage(self):
        max_usage = 0
        u_run_time = 0
        s_run_time = 0
        while self.keep_measuring:
            max_usage = max(max_usage, getrusage(RUSAGE_SELF).ru_maxrss)
            u_run_time = max(u_run_time, getrusage(RUSAGE_SELF).ru_utime) 
            s_run_time = max(s_run_time, getrusage(RUSAGE_SELF).ru_stime) 
        sleep(0.1) # run this loop every 0.1 seconds
        return [max_usage, u_run_time, s_run_time]

def execute(function):
    with ThreadPoolExecutor() as executor:
        monitor = MemoryMonitor()
        stats_thread = executor.submit(monitor.measure_usage)
        try:
            fn_thread = executor.submit(function)
            result = fn_thread.result()
            print("print result")
            print(result)
            print("print result type")
            print(type(result))
        finally:
            monitor.keep_measuring = False
            stats = stats_thread.result()
        print(stats)
        return result

def foo():
    i = 0
    while i < 3:
        print("foo")
        i+=1
    return 1

def bar(x):
    while x < 3:
        print("foobar")
        x+=1
    return 1

var = execute(foo)
print("Var = " + str(var))
var = execute(bar(0))
print("Var = " + str(var))

Se eu passar a função foo como um argumento para a função execute , ela imprime os resultados corretos e retorna o valor retornado por foo.

Se eu passar a barra de funções da mesma maneira, mas com a própria barra exigindo um argumento, a função é executada (imprime 3 vezes) e recebo o seguinte erro:

result = self.fn(*self.args, **self.kwargs)
TypeError: 'int' object is not callable

Após alguns testes, a parte em que estou preso parece estar passando uma função como um argumento, se essa função em si exigir um argumento. Pelo que entendi do ThreadPoolExecutor, o objeto fn_thread encapsula a execução da função enviada. O objeto de resultado deve simplesmente conter o resultado dessa execução - o que estou perdendo para que isso não possa lidar com a transmissão de uma função com um argumento?

Respostas

3 AleksJ Aug 26 2020 at 15:08

Você está enviando

bar(0) 

ao invés de

bar, 0

Para esclarecer, observe a assinatura do envio: enviar (fn, * args, ** kwargs)

o resultado de

bar(0)

é um inteiro, e o executor não pode chamar um inteiro, uma vez que não é 'chamável', como a mensagem de erro sugere.