2010-01-12 18 views
41
import subprocess 

def my_function(x): 
    return x + 100 

output = subprocess.Popen(my_function, 1) #I would like to pass the function object and its arguments 
print output 
#desired output: 101 

Je n'ai trouvé la documentation sur l'ouverture des scripts séparés en utilisant des sous-processus. Est-ce que quelqu'un sait comment passer des objets de fonction ou même un moyen facile de passer le code de fonction?Est-il possible d'exécuter la fonction dans un sous-processus sans enfiler ou écrire un fichier/script séparé.

+1

Je crois que vous êtes à la recherche du module [multitraitement] (http://docs.python.org/3.1/library/multiprocessing.html). –

Répondre

65

Je pense que vous cherchez quelque chose de plus comme le module de multitraitement:

http://docs.python.org/library/multiprocessing.html#the-process-class

Le module subprocess est pour les processus de reproduction et de faire des choses avec leur entrée/sortie - pas pour les fonctions en cours d'exécution.

Voici une version multiprocessing de votre code:

from multiprocessing import Process, Queue 

def my_function(q, x): 
    q.put(x + 100) 

if __name__ == '__main__': 
    queue = Queue() 
    p = Process(target=my_function, args=(queue, 1)) 
    p.start() 
    p.join() # this blocks until the process terminates 
    result = queue.get() 
    print result 
+13

Vous pouvez utiliser le décorateur 'processify' comme raccourci: https://gist.github.com/2311116 – schlamar

+1

Je suppose que ce clone l'interpréteur Python et tout son environnement pour le sous-processus? – Jens

+0

Voici un fork de processify qui fonctionne en python 3 et supporte les fonctions de générateur. https://gist.github.com/stuaxo/889db016e51264581b50 –

14

Vous pouvez utiliser le standard appel système Unix fork, comme os.fork(). fork() va créer un nouveau processus, avec le même script en cours d'exécution. Dans le nouveau processus, il retournera 0, tandis que dans l'ancien processus, il retournera l'identifiant de processus du nouveau processus.

child_pid = os.fork() 
if child_pid == 0: 
    print "New proc" 
else: 
    print "Old proc" 

Pour une bibliothèque de niveau supérieur, qui fournit le support multiprocesseurs qui fournit une abstraction portable pour l'utilisation de plusieurs processus, il y a le module multiprocessing. Il y a un article sur IBM DeveloperWorks, Multiprocessing with Python, avec une brève introduction aux deux techniques. post ci-dessus de

+0

Je suis curieux; pourquoi la downvote? Y a-t-il quelque chose qui ne va pas dans ma réponse? –

+0

Le multitraitement n'est pas seulement un wrapper de niveau supérieur autour de fork(), c'est un toolkit multi-traitement multiplateforme (qui utilise fork sur unix). Ce qui est important, car cela signifie qu'il fonctionne sur, disons, Windows, alors que fork() ne fonctionne pas. Edit: Et c'était la raison de la downvote, bien que j'ai décidé plus tard, il ne valait probablement pas la peine. Trop tard pour le reprendre, cependant. Edit2: Ou plutôt, fork() étant suggéré quand il n'est pas multi-plateforme était la raison. –

+1

@Devin, vous pouvez toujours reprendre un downvote que vous avez fait, si vous le souhaitez. –

3

Brian McKenna à propos de multitraitement est vraiment utile, mais si vous voulez aller dans la voie filetée (opposition au processus basé), cet exemple vous aider à démarrer:

import threading 
import time 

def blocker(): 
    while True: 
     print "Oh, sorry, am I in the way?" 
     time.sleep(1) 

t = threading.Thread(name='child procs', target=blocker) 
t.start() 

# Prove that we passed through the blocking call 
print "No, that's okay" 

Vous pouvez également utiliser la fonctionnalité setDaemon(True) pour mettre en arrière-plan le fil immédiatement.