2010-06-26 4 views
1

Je suis à la recherche d'un moyen d'alléger mon code fileté.simplifier le filetage en python

Il y a beaucoup d'endroits dans mon code où je fais quelque chose comme:

for arg in array: 
    t=Thread(lambda:myFunction(arg)) 
    t.start() 

i.e. exécutant la même fonction, chaque fois que des paramètres différents, dans les discussions. Ceci est bien sûr une version simplifiée du code réel, et généralement le code à l'intérieur de la boucle for est ~ 10-20 lignes de long, qui ne peut être rendu simple en utilisant une fonction auxiliaire comme myFunction dans l'exemple ci-dessus (avait ça a été le cas, j'aurais pu utiliser un pool de threads).

En outre, ce scénario est très, très commun dans mon code, donc il y a des tonnes de lignes que je considère comme redondantes. Cela me aiderait beaucoup si je ne l'ai pas besoin de gérer tout ce code passe-partout, mais être capable de faire quelque chose comme:

for arg in array: 
     with threaded(): 
      myFunction(arg) 

-à-dire en quelque sorte prend chaque ligne de code à l'intérieur et l'exécute dans un fil séparé.

Je sais que les gestionnaires de contexte ne sont pas censés être utilisés dans de telles situations, que c'est probablement une mauvaise idée et qu'il faudra un bidouillage moche, mais néanmoins - peut-il être fait, et comment?

+0

Je me demande pourquoi vous en avez besoin. Vous * êtes * conscient du fait que les threads Python ne fonctionnent pas en parallèle sur plusieurs cœurs/processeurs, n'est-ce pas? –

+0

@Eli: Son code ne pourrait pas être lié à l'IO, n'est-ce pas? :) –

+0

@Mark: en fait, c'est pourquoi j'ai demandé. Son cas d'utilisation ne semble pas lié à l'IO. Il pourrait être, donc je me demande ce que c'est - toujours prêt à apprendre, vous savez :-) –

Répondre

0

Un pool de threads pourrait-il vous aider ici? De nombreuses implémentations pour Python existent, par exemple this one.


P.S: toujours intéressé de savoir ce que votre cas d'utilisation est

+0

Je ne vois rien dans sa question indiquant une implémentation de Python dans GIL. –

0

exacte Qu'est-ce que vous voulez est une sorte de « pool de threads contextuel ». Jetez un oeil à la classe ThreadPool au this module, conçue pour être utilisée de la même manière que vous l'avez fait. Utilisez serait quelque chose comme ceci:

with ThreadPool() as pool: 
    for arg in array: 
     pool.add_thread(target=myFunction, args=[arg]) 

échecs dans une tâche donnée à un ThreadPool marquera une erreur, et effectuer l'erreur type manipulation Backtrace.

+0

Notez bien sûr que vous ajustez ceci à votre goût syntaxique, mais j'aime bien l'interface 'threading.Thread' standard, et je l'ai adapté. –

+0

Merci, mais il me faut encore définir explicitement 'myFunction', qui est le genre de fouillis que j'essaie d'éviter ... C'était de ma faute, j'aurais dû le souligner plus dans ma question. Je vais l'éditer. – olamundo

0

Je pense que vous êtes trop compliquer. C'est le « pattern » J'utilise:

# util.py 
def start_thread(func, *args): 
    thread = threading.Thread(target=func, args=args) 
    thread.setDaemon(True) 
    thread.start() 
    return thread 

# in another module 
import util 
... 
for arg in array: 
    util.start_thread(myFunction, arg) 

Je ne vois pas le gros problème d'avoir à créer myFunction. Vous pouvez même définir la fonction en ligne avec la fonction qui la démarre.

def do_stuff(): 
    def thread_main(arg): 
     print "I'm a new thread with arg=%s" % arg 
    for arg in array: 
     util.start_thread(thread_main, arg) 

Si vous créez un grand nombre de threads, un pool de threads a définitivement plus de sens. Vous pouvez facilement créer le vôtre avec les modules Queue et threading. Fondamentalement créer une file d'attente jobs, créer N threads de travail, donner à chaque thread un "pointeur" à la file d'attente et les faire tirer des travaux de la file d'attente et les traiter.

1

Que diriez-vous ceci:

for arg in array: 
    def _thread(): 
     # code here 
     print arg 

    t = Thread(_thread) 
    t.start() 

En outre, avec les décorateurs, vous pouvez le sucre il un peu:

def spawn_thread(func): 
    t = Thread(func) 
    t.start() 
    return t 

for arg in array: 
    @spawn_thread 
    def _thread(): 
     # code here 
     print arg 
+0

pCela m'a presque convaincu, mais le problème est la portée de vos args. si vous pour i dans la plage (10): @spawn_thread def f(): sommeil (1) impression i vous obtenez '9 9 9 9 9 9 9 9 9 9 9' que votre sortie – olamundo