Python filetage plusieurs bash sous-processus?

comment utiliser les modules de filetage et de sous-processus pour générer des processus de bash en parallèle? Quand je démarre les threads ala la première réponse ici: comment utiliser le threading en Python? , les processus de bash fonctionnent de manière séquentielle au lieu d'en parallèle.

30
demandé sur Community 2013-01-26 07:09:25

3 réponses

vous n'avez pas besoin de threads pour exécuter des sous-processus en parallèle:

from subprocess import Popen

commands = [
    'date; ls -l; sleep 1; date',
    'date; sleep 5; date',
    'date; df -h; sleep 3; date',
    'date; hostname; sleep 2; date',
    'date; uname -a; date',
]
# run in parallel
processes = [Popen(cmd, shell=True) for cmd in commands]
# do other things here..
# wait for completion
for p in processes: p.wait()

pour limiter le nombre de commandes concurrentes, vous pouvez utiliser multiprocessing.dummy.Pool qui utilise des threads et fournit la même interface que multiprocessing.Pool qui utilise des processus:

from functools import partial
from multiprocessing.dummy import Pool
from subprocess import call

pool = Pool(2) # two concurrent commands at a time
for i, returncode in enumerate(pool.imap(partial(call, shell=True), commands)):
    if returncode != 0:
       print("%d command failed: %d" % (i, returncode))

cette réponse démontre diverses techniques pour limiter le nombre de sous-processus concurrents : elle montre multitraitement.Piscine, concurrente.futures, threading + file-based solutions.


vous pouvez limiter le nombre de processus enfants concurrents sans utiliser de thread / process pool:

from subprocess import Popen
from itertools import islice

max_workers = 2  # no more than 2 concurrent processes
processes = (Popen(cmd, shell=True) for cmd in commands)
running_processes = list(islice(processes, max_workers))  # start new processes
while running_processes:
    for i, process in enumerate(running_processes):
        if process.poll() is not None:  # the process has finished
            running_processes[i] = next(processes, None)  # start new process
            if running_processes[i] is None: # no new processes
                del running_processes[i]
                break

sur Unix, vous pouvez éviter la boucle occupée et bloquer sur os.waitpid(-1, 0) , pour attendre que n'importe quel processus enfant de sortir .

47
répondu jfs 2017-05-23 10:30:46

exemple simple de filetage:

import threading
import Queue
import commands
import time

# thread class to run a command
class ExampleThread(threading.Thread):
    def __init__(self, cmd, queue):
        threading.Thread.__init__(self)
        self.cmd = cmd
        self.queue = queue

    def run(self):
        # execute the command, queue the result
        (status, output) = commands.getstatusoutput(self.cmd)
        self.queue.put((self.cmd, output, status))

# queue where results are placed
result_queue = Queue.Queue()

# define the commands to be run in parallel, run them
cmds = ['date; ls -l; sleep 1; date',
        'date; sleep 5; date',
        'date; df -h; sleep 3; date',
        'date; hostname; sleep 2; date',
        'date; uname -a; date',
       ]
for cmd in cmds:
    thread = ExampleThread(cmd, result_queue)
    thread.start()

# print results as we get them
while threading.active_count() > 1 or not result_queue.empty():
    while not result_queue.empty():
        (cmd, output, status) = result_queue.get()
        print('%s:' % cmd)
        print(output)
        print('='*60)
    time.sleep(1)

notez qu'il y a de meilleures façons de le faire, mais ce n'est pas trop compliqué. L'exemple utilise un thread pour chaque commande. La complexité commence à s'infiltrer quand vous voulez faire des choses comme utiliser un nombre limité de threads pour gérer un nombre inconnu de commandes. Ces techniques plus avancées ne semblent pas trop compliquées une fois que vous avez une compréhension des bases filetage. Et le multiprocesseur devient plus facile une fois que vous avez une poignée sur ces techniques.

6
répondu rzzzwilson 2013-01-26 04:17:11

c'est parce qu'il est censé faire, la chose que vous voulez faire n'est pas multithreadind mais multiprocessing voir ce stack page

0
répondu Magaly Alonzo 2017-05-23 12:02:54