Python Executor - Fonction de transmission avec argument comme argument

Aug 26 2020

Mon objectif est de créer une fonction que je peux utiliser pour mesurer l'exécution et l'utilisation des ressources d'une autre fonction. À l'aide d'un didacticiel, j'ai créé ce qui suit en utilisant ThreadPoolExecutor de 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))

Si je passe la fonction foo comme argument à la fonction execute , elle imprime les résultats corrects et renvoie la valeur renvoyée par foo.

Si je passe la barre de fonctions de la même manière, mais avec la barre elle-même nécessitant un argument, la fonction s'exécute (s'imprime 3 fois) et j'obtiens l'erreur suivante:

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

Après quelques tests, la partie où je suis bloqué semble passer une fonction en tant qu'argument, si cette fonction elle-même nécessite un argument. Si je comprends bien ThreadPoolExecutor, l' objet fn_thread encapsule l'exécution de la fonction soumise. L' objet résultat devrait simplement contenir le résultat de cette exécution - que me manque-t-il pour que cela ne puisse pas gérer le passage d'une fonction avec un argument?

Réponses

3 AleksJ Aug 26 2020 at 15:08

Vous soumettez

bar(0) 

au lieu de

bar, 0

Pour clarifier, regardez la signature de la soumission: submit (fn, * args, ** kwargs)

Le résultat de

bar(0)

est un entier, et l'exécuteur ne peut pas appeler un entier, car il n'est pas «appelable», comme le suggère le message d'erreur.