Necesito ejecutar múltiples comandos en Linux usando python al mismo tiempo. No necesito ejecutarlo comando por comando.

Intento escribir este código, pero no puedo entender cómo ejecutar varios comandos al mismo tiempo usando Python, también leí sobre Python multihilo, pero no sé cómo usarlo.

Código:

#  -*- coding: utf-8 -*-

import os

commands = ['ping www.google.com', 'ping www.yahoo.com', 'ping www.hotmail.com']
count = 0
for com in commands:
    print "Start execute commands.."
    os.system(com)
    count += 1
    print "[OK] command "+str(count)+" runing successfully."
else:
    print "Finish.."

¿Por favor, cómo puedo hacer eso con Python y ejecutar múltiples comandos al mismo tiempo?

2
Mahmoud Al-Nafei 7 may. 2016 a las 22:15

4 respuestas

La mejor respuesta

Parece un problema típico de productor-consumidor

import threading
import os

commands = ['ping www.google.com', 'ping www.yahoo.com', 'ping www.hotmail.com']

def worker_func():
    while commands:   # Checks if the the list is not-empty. Loop exits when list is becomes empty
        com = commands.pop(0)
        print "Start execute commands.."
        os.system(com)
        count += 1
        print "[OK] command "+str(count)+" runing successfully."

workers = [threading.Thread(target=worker_func, args=tuple(), name='thread_'+str(i))  for i in range(5) ]  # Create 5 workers (consumers)
[worker.start() for worker in workers]  # Start working
[worker.join() for worker in workers]   # Wait for all workers to finish

Aquí he creado los 5 hilos de trabajo. Estos subprocesos ejecutarán la función worker_func.
worker_func Recogerá un elemento de la lista y realizará el trabajo. Cuando la lista se vacía, la función regresa (sale).

Nota : Lea acerca de Bloqueo global del intérprete para comprender dónde no debería utilizarse el subprocesamiento múltiple de Python ser utilizado.
En este caso, el GIL (Global Interpreter Lock) no debería afectarlo porque worker_func llama a un subproceso y espera a que se complete. Mientras el hilo está esperando, GIL se libera a otros hilos.

2
shanmuga 7 may. 2016 a las 19:43
import threading
import os


def ping_url(number):

    os.system(number)

thread_list = []
commands = ['ping www.google.com', 'ping www.yahoo.com', 'ping www.hotmail.com']
for url in commands:
    # Instantiates the thread

    t = threading.Thread(target=print_number, args=(url,))
    # Sticks the thread in a list so that it remains accessible
    thread_list.append(t)

# Starts threads
for thread in thread_list:
    thread.start()

# This blocks the calling thread until the thread whose join() method is called is terminated.
# From http://docs.python.org/2/library/threading.html#thread-objects
for thread in thread_list:
    thread.join()

# Demonstrates that the main process waited for threads to complete
print "Done"
0
Hafees Kazhunkil 7 may. 2016 a las 19:36

Mi solución no inicia hilos adicionales.
Uso subprocess.Popen para ejecutar un comando, almacenar objetos Popen en una lista en el primer bucle y esperar hasta que los subprocesos terminen en el segundo

from subprocess import Popen, PIPE

commands = ['ping www.google.com', 'ping www.yahoo.com', 'dir']
count = 0
processes = []
for com in commands:
    print "Start execute commands.."
    processes.append(Popen(com, shell=True))
    count += 1
    print "[OK] command "+str(count)+" running successfully."
else:
    print "Finish.."

for i, process in enumerate(processes):
    process.wait()
    print "Command #{} finished".format(i)
2
robyschek 7 may. 2016 a las 20:18

Estoy sugiriendo dos soluciones pero hay muchas

Solución simple :

Use & al final de sus comandos para ejecutarlos en segundo plano:

commands = ['ping www.google.com &', 'ping www.yahoo.com &', 'ping www.hotmail.com &']
for com in commands:
    os.system(com) # now commands will run in background

Threading + solución de cola con un control sobre los hilos máximos para generar:

from Queue import Queue, Empty
import threading, os

def worker_func():
    while not stopped.is_set():
        try:
            # use the get_nowait() method for retrieving a queued item to
            # prevent the thread from blocking when the queue is empty
            com = q.get_nowait()
        except Empty:
            continue
        try:
            os.system(com)
        except Exception as e:
            print "[-] Error running command %s" %(str(e))
        finally:
            q.task_done()

commands = ['ping www.google.com', 'ping www.yahoo.com', 'ping www.hotmail.com']

thread_count = 4 # maximum parallel threads 
stopped = threading.Event()
q = Queue()
print "-- Processing %s tasks in thread queue with %s thread limit" %(str(len(commands)), str(thread_count))

for item in commands:
    q.put(item)

for i in range(thread_count):
     t = threading.Thread(target=worker_func)
     # t.daemon = True #Enable to run threads as daemons
     t.start()
q.join()       # block until all tasks are done
stopped.set()
2
Shark 7 may. 2016 a las 20:04