Maison  >  Article  >  développement back-end  >  Introduction au futur module concurrent en Python (code)

Introduction au futur module concurrent en Python (code)

不言
不言original
2018-08-30 09:55:402665parcourir

Cet article vous apporte une introduction (code) sur le futur module concurrent en Python. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il vous sera utile.

module concurrent.futures

La principale caractéristique de ce module est les classes ThreadPoolExecutor et ProcessPoolExecutor. Les deux classes héritent de la classe concurrent.futures._base.Executor. Les interfaces qu'elles implémentent peuvent être utilisées. dans différents objets Callable sont exécutés dans des threads ou des processus, et ils maintiennent tous un thread de travail ou un pool de processus en interne.

Les classes ThreadPoolExecutor et ProcessPoolExecutor sont des classes avancées. Dans la plupart des cas, il vous suffit d'apprendre à les utiliser sans prêter attention aux détails de leur implémentation.

####Classe ProcessPoolExecutor

>class ThreadPoolExecutor(concurrent.futures._base.Executor)

>|  This is an abstract base class for concrete asynchronous executors.

>|  Method resolution order:

>|      ThreadPoolExecutor

 |      concurrent.futures._base.Executor

 |      builtins.object

 |

 |  Methods defined here:

 |

 |  init(self, max_workers=None, thread_name_prefix='')

 |      Initializes a new ThreadPoolExecutor instance.

 |

 |      Args:

 |          max_workers: The maximum number of threads that can be used to

 |              execute the given calls.

 |          thread_name_prefix: An optional name prefix to give our threads.

 |

 |  shutdown(self, wait=True)

 |      Clean-up the resources associated with the Executor.

 |

 |      It is safe to call this method several times. Otherwise, no other

 |      methods can be called after this one.

 |

 |      Args:

 |          wait: If True then shutdown will not return until all running

 |              futures have finished executing and the resources used by the

 |              executor have been reclaimed.

 |

 |  submit(self, fn, *args, **kwargs)

 |      Submits a callable to be executed with the given arguments.

 |

 |      Schedules the callable to be executed as fn(*args, **kwargs) and returns

 |      a Future instance representing the execution of the callable.

 |

 |      Returns:

 |          A Future representing the given call.

 |

 |  ----------------------------------------------------------------------

 |  Methods inherited from concurrent.futures._base.Executor:

 |

 |  enter(self)

 |

 |  exit(self, exc_type, exc_val, exc_tb)

 |

 |  map(self, fn, *iterables, timeout=None, chunksize=1)

 |      Returns an iterator equivalent to map(fn, iter).

 |

 |      Args:

 |          fn: A callable that will take as many arguments as there are

 |              passed iterables.

 |          timeout: The maximum number of seconds to wait. If None, then there

 |              is no limit on the wait time.

 |          chunksize: The size of the chunks the iterable will be broken into

 |              before being passed to a child process. This argument is only

 |              used by ProcessPoolExecutor; it is ignored by

 |              ThreadPoolExecutor.

 |

 |      Returns:

 |          An iterator equivalent to: map(func, *iterables) but the calls may

 |          be evaluated out-of-order.

 |

 |      Raises:

 |          TimeoutError: If the entire result iterator could not be generated

 |              before the given timeout.

 |          Exception: If fn(*args) raises for any values.

L'initialisation peut spécifier un nombre maximum de processus comme valeur de son paramètre max_workers. Cette valeur n'a généralement pas besoin d'être spécifiée. le nombre de cœurs de la machine actuellement en cours d'exécution. Il peut être obtenu par os.cpu_count(); la classe contient des méthodes :

  1. méthode map(), qui a une fonction similaire à celle de python. méthode intégrée map(), c'est-à-dire le mappage, et les paramètres sont :

  • Une fonction appelable fn

  • Un itérateur itérable

  • Timeout Durée timeout

  • Nombre de morceaux chunksize Si supérieur à 1, l'itérateur sera traité en morceaux

---->> Cette fonction a une caractéristique : le résultat du retour est cohérent avec l'ordre dans lequel l'appel est lancé, il n'y aura pas de blocage pendant le processus d'appel, ce qui signifie que l'exécution de ce dernier peut avoir été achevée avant que le premier ne soit appelé.

Si vous devez obtenir tous les résultats avant le traitement, vous pouvez choisir d'utiliser la méthode submit() en combinaison avec la fonction futures.as_completed. Méthode

  1. shutdown(), nettoie toutes les ressources liées à l'exécuteur actuel (exécuteur)

  2. méthodesubmit(), soumet un appelable. l'objet utilise fn

  3. hérite des méthodes __enter__() et __exit__() de concurrent.futures._base.Executor, ce qui signifie que les objets ProcessPoolExecutor peuvent être utilisés dans les instructions with.

from concurrent import futures
with futures.ProcessPoolExecutor(max_works=3) as executor:
     executor.map()

La classe ThreadPoolExecutor

class ThreadPoolExecutor(concurrent.futures._base.Executor)

 |  This is an abstract base class for concrete asynchronous executors.

 |

 |  Method resolution order:

 |      ThreadPoolExecutor

 |      concurrent.futures._base.Executor

 |      builtins.object

 |

 |  Methods defined here:

 |

 |  init(self, max_workers=None, thread_name_prefix='')

 |      Initializes a new ThreadPoolExecutor instance.

 |

 |      Args:

 |          max_workers: The maximum number of threads that can be used to

 |              execute the given calls.

 |          thread_name_prefix: An optional name prefix to give our threads.

 |

 |  shutdown(self, wait=True)

 |      Clean-up the resources associated with the Executor.

 |

 |      It is safe to call this method several times. Otherwise, no other

 |      methods can be called after this one.

 |

 |      Args:

 |          wait: If True then shutdown will not return until all running

 |              futures have finished executing and the resources used by the

 |              executor have been reclaimed.

 |

 |  submit(self, fn, *args, **kwargs)

 |      Submits a callable to be executed with the given arguments.

 |

 |      Schedules the callable to be executed as fn(*args, **kwargs) and returns

 |      a Future instance representing the execution of the callable.

 |

 |      Returns:

 |          A Future representing the given call.

 |

 |  ----------------------------------------------------------------------

 |  Methods inherited from concurrent.futures._base.Executor:

 |

 |  enter(self)

 |

 |  exit(self, exc_type, exc_val, exc_tb)

 |

 |  map(self, fn, *iterables, timeout=None, chunksize=1)

 |      Returns an iterator equivalent to map(fn, iter).

 |

 |      Args:

 |          fn: A callable that will take as many arguments as there are

 |              passed iterables.

 |          timeout: The maximum number of seconds to wait. If None, then there

 |              is no limit on the wait time.

 |          chunksize: The size of the chunks the iterable will be broken into

 |              before being passed to a child process. This argument is only

 |              used by ProcessPoolExecutor; it is ignored by

 |              ThreadPoolExecutor.

 |

 |      Returns:

 |          An iterator equivalent to: map(func, *iterables) but the calls may

 |          be evaluated out-of-order.

 |

 |      Raises:

 |          TimeoutError: If the entire result iterator could not be generated

 |              before the given timeout.

 |          Exception: If fn(*args) raises for any values.

est très similaire à la classe ProcessPoolExecutor, sauf que l'une est un processus de traitement et l'autre est un thread de traitement, ce qui peut être sélectionné en fonction des besoins réels.

Exemple

from time import sleep, strftime
from concurrent import futures


def display(*args):
    print(strftime('[%H:%M:%S]'), end="")
    print(*args)


def loiter(n):
    msg = '{}loiter({}): doing nothing for {}s'
    display(msg.format('\t'*n, n, n))
    sleep(n)
    msg = '{}loiter({}): done.'
    display(msg.format('\t'*n, n))
    return n*10


def main():
    display('Script starting')
    executor = futures.ThreadPoolExecutor(max_workers=3)
    results = executor.map(loiter, range(5))
    display('results:', results)
    display('Waiting for inpidual results:')
    for i, result in enumerate(results):
        display('result {} : {}'.format(i, result))


if __name__ == '__main__':
    main()

Résultats d'exécution :

[20:32:12]Script starting
[20:32:12]loiter(0): doing nothing for 0s
[20:32:12]loiter(0): done.
[20:32:12]      loiter(1): doing nothing for 1s
[20:32:12]              loiter(2): doing nothing for 2s
[20:32:12]results: <generator object Executor.map.<locals>.result_iterator at 0x00000246DB21BC50>
[20:32:12]Waiting for inpidual results:
[20:32:12]                      loiter(3): doing nothing for 3s
[20:32:12]result 0 : 0
[20:32:13]      loiter(1): done.
[20:32:13]                              loiter(4): doing nothing for 4s
[20:32:13]result 1 : 10
[20:32:14]              loiter(2): done.
[20:32:14]result 2 : 20
[20:32:15]                      loiter(3): done.
[20:32:15]result 3 : 30
[20:32:17]                              loiter(4): done.
[20:32:17]result 4 : 40

Les résultats d'exécution peuvent être différents sur différentes machines.

Dans l'exemple, max_workers=3 est défini, donc dès que le code commence à s'exécuter, trois objets (0, 1, 2) sont exécutés avec l'opération loiter() après trois secondes, l'opération de ; l'objet 0 se termine et le résultat est le résultat 0. Après cela, l'objet 3 commence à être exécuté de même, le temps d'exécution de l'objet 4 est après l'impression du résultat 1, le résultat de l'exécution de l'objet 1.

Recommandations associées :

Exemples détaillés de la façon dont Python gère les problèmes de concurrence via les contrats à terme

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn