Sto provando a scrivere uno script che richiederà più percorsi ai file su vari server, li cercherà tutti contemporaneamente e restituirà un singolo elenco di risultati a un utente. Inizialmente, stavo usando solo i thread Python per fare ciò, tuttavia ho riscontrato alcuni problemi noti:
-
Non stavo controllando quanti thread potevano essere avviati. Quindi se qualcuno inviava 100 file per interrogare un server, avresti 100 thread avviati su quella macchina, che erano cattive notizie.
-
I risultati che stavo tornando erano incompleti e variati drasticamente. Se eseguissi le ricerche in modo lineare (senza discussioni), otterrei risultati completi, ma ci sarebbe voluto molto tempo. Ho concluso basandomi su questa e alcune ricerche personali che non stavo adottando un approccio sicuro per i thread e ho iniziato a esaminare il modulo Queue.
Ho finito con qualcosa di simile ...
def worker():
while q.qsize != 0:
cmd = q.get()
# kick off a bash command that zgreps files from different servers
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
results.extend(''.join(p.stdout.readlines()).split('\n')[:-1])
q.task_done()
NUM_WORKER_THREADS = 10
results = []
q = Queue.Queue()
for i in range(NUM_WORKER_THREADS):
t = threading.Thread(target=worker)
t.daemon = True
t.start()
""" Code to generate input commands needed here """
for c in commands:
q.put(c)
q.join()
""" Post processing of collected *results* array"""
Dopo aver inserito alcuni vincoli del pool di thread attorno al mio programma e aver controllato ogni thread se c'è ancora qualcosa nella coda, i miei risultati sono in linea con quello che mi aspetterei. Dopo il test, i risultati corrispondono all'output di un singolo approccio filettato (tranne che è molto più veloce).
Le mie domande sono le seguenti:
-
Il mio approccio è thread-safe? C'è qualche possibilità che uno dei 10 thread di lavoro possa sovrascrivere un tentativo di estendere l'array di risultati? Sono preoccupato che abbia appena diminuito le possibilità di sovrascrittura, allocando un pool di thread più piccolo per gestire l'input, ma in realtà non abbiamo risolto il problema.
-
Capisco dalla lettura che le code dovrebbero essere thread-safe. Tuttavia, quando elimino i pool di thread e non controllo la dimensione della coda nei thread, posso riprodurre lo stesso problema che avevo prima con grandi volumi di input. Qualcuno può spiegare perché è così?