Ceci est un mémorandum sur l'utilisation du module concurrent.futures ajouté à partir de Python version 3.2.
Le module concurrent.futures
, en conclusion, fournit à la fois des interfaces multi-thread et multi-processus.
Q. Que faire si un problème parallèle ne correspond pas à une application asynchrone ou si vous ne savez pas quoi faire?
A. Déléguez le traitement de la partie problématique à un thread ou un processus. Il donne au traitement délégué l'apparence d'un collout, libère le contrôle de la boucle d'événements et traite le résultat final.
Le module concurrent.future
est prêt à réaliser cette A.
Le module concurrent.future
est également intégré dans le module ʻasycio`, et en combinant ces deux modules, vous pouvez utiliser des fonctions de blocage qui sont exécutées dans plusieurs threads ou processus comme s'il s'agissait de collouties asynchrones non bloquantes.
Le module concurrent.future
a un objet ʻExecutor et un objet
Future`.
ʻExecutorreprésente un ** pool ** de ressources qui peuvent traiter des éléments de travail en parallèle. Il semble avoir un but similaire à la classe
Pool du module
multiprocessing`, mais avec une conception différente de celle de l'interface.
** La classe ʻExecutor est une classe de base qui n'est pas instanciée **. La classe ʻExecutor
a les deux sous-classes suivantes.
ThreadPoolExecutor
: Spécifiez le pool de threads et effectuez un traitement asynchrone.ProcessPollExecutor
: Spécifiez le pool de processus et effectuez un traitement asynchrone.De ces faits, on peut dire que la classe ʻExecutor` fournit à la fois des interfaces multi-thread et multi-processus.
Ces classes fournissent trois méthodes.
submit (fn, * args, ** kwargs)
: Planifie la fonction fn pour qu'elle s'exécute dans le pool de ressources et renvoie un objet Future
map (func, * iterables, timeout = None, chunksize = 1)
: Similaire à la méthode multiprocessing.Pool.map ()
, exécutez la fonction func
sur chaque élément de l'objet itérable. Je vais.shutdown (wait = True)
: ʻExecutor` s'arrête et libère toutes les ressources.Voici un exemple de mise en œuvre.
geocoding_by_concurrentfutures.py
from gmaps import Geocoding
from concurrent.futures import ThreadPoolExecutor
api = Geocoding(api_key='maruhi')
PLACES = (
'Reykjavik', 'Vien', 'Zadar',
'Venice', 'Wrocow', 'Bolognia',
'Berlin', 'Dehil', 'New York',
'Osaka'
)
POOL_SIZE = 4
def fetch_place(place):
return api.geocode(place)[0]
def present_result(geocoded):
print("{:s}, {:6.2f}, {:6.2f}".format(
geocoded['formatted_address'],
geocoded['geometry']['location']['lat'],
geocoded['geometry']['location']['lng'],
))
def main():
with ThreadPoolExecutor(POOL_SIZE) as executor:
results = executor.map(fetch_place, PLACES)
print(type(results))
print(results)
for result in results:
present_result(result)
if __name__ == "__main__":
main()
$python geocoding_by_concurrentfutures.py
<class 'generator'>
<generator object _chain_from_iterable_of_lists at 0x000001E2A3CED9C8>
Reykjavík, Iceland, 64.15, -21.94
3110 Glendale Blvd, Los Angeles, CA 90039, USA, 34.12, -118.26
Zadar, Croatia, 44.12, 15.23
Venice, Metropolitan City of Venice, Italy, 45.44, 12.32
Wrocław, Poland, 51.11, 17.04
Bologna, Metropolitan City of Bologna, Italy, 44.49, 11.34
Berlin, Germany, 52.52, 13.40
Delhi, India, 28.70, 77.10
New York, NY, USA, 40.71, -74.01
Osaka, Japan, 34.69, 135.50
Future
La classe Future
est générée par la fonction ʻExecutor.submit (). L'objet
Futuregère l'exécution asynchrone des objets appelables et affiche les résultats du traitement. La valeur de retour de l'objet appelable enregistré est obtenue par la méthode
Future.result (). ** Si ce n'est pas terminé, bloquez jusqu'à ce que le résultat soit prêt. ** L'acquisition du résultat par la méthode
result ()ne doit pas nécessairement être postérieure à la fin du traitement, et
result ()` attend la fin et renvoie la valeur.
[À propos des objets futurs (officiels)] https://docs.python.org/ja/3/library/concurrent.futures.html#future-objects
sample_concurrent_futures.py
from concurrent.futures import ThreadPoolExecutor
def loudy_return():
print("processing")
return 42
with ThreadPoolExecutor(1) as executor:
future = executor.submit(loudy_return)
print(future)
print(future.result())
$python sample_concurrent_futures.py
processing
<Future at 0x27f17bd76c8 state=finished returned int>
42
Recommended Posts