Python Threading stdin/stdout
Ich habe eine Datei, die enthält eine Menge von Daten. Jede Zeile ist ein Datensatz. Und ich bin versucht zu tun, einige ETL-Arbeit gegen die ganze Datei. Jetzt bin ich mit standard-input zum Lesen der Daten Zeile für Zeile. Die kühle Sache über dieses ist, Ihr Skript könnte sehr flexibel sein, um die Integration mit anderen script-und shell-Befehle. Ich Schreibe das Ergebnis auf die Standardausgabe. Zum Beispiel.
$ cat input_file
line1
line2
line3
line4
...
Meine aktuelle python-code sieht wie folgt aus - parse.py
import sys
for line in sys.stdin:
result = ETL(line) # ETL is some self defined function which takes a while to execute.
print result
Den code unten ist, wie es funktioniert jetzt:
cat input_file | python parse.py > output_file
Ich habe mir das Threading-Modul von Python und ich Frage mich, ob das würde die Leistung drastisch verbessert, wenn ich das Modul.
Frage 1: Wie sollte ich planen die Quoten für jeden thread, warum?
...
counter = 0
buffer = []
for line in sys.stdin:
buffer.append(line)
if counter % 5 == 0: # maybe assign 5 rows to each thread? if not, is there a rule of thumb to determine
counter = 0
thread = parser(buffer)
buffer = []
thread.start()
Question2: Mehrere Threads, vielleicht drucken Sie das Ergebnis wieder auf stdout zur gleichen Zeit, wie Sie zu organisieren und zu vermeiden, die situation da unten?
import threading
import time
class parser(threading.Thread):
def __init__ (self, data_input):
threading.Thread.__init__(self)
self.data_input = data_input
def run(self):
for elem in self.data_input:
time.sleep(3)
print elem + 'Finished'
work = ['a', 'b', 'c', 'd', 'e', 'f']
thread1 = parser(['a', 'b'])
thread2 = parser(['c', 'd'])
thread3 = parser(['e', 'f'])
thread1.start()
thread2.start()
thread3.start()
Die Ausgabe ist wirklich hässlich, wo eine Zeile enthält, die Ausgänge von zwei threads.
aFinished
cFinishedeFinished
bFinished
fFinished
dFinished
InformationsquelleAutor B.Mr.W. | 2013-08-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nehmen Ihre zweite Frage zuerst, das ist, was Mutexe sind. Sie können den Reiniger Ausgabe, die Sie wollen, indem Sie eine Sperre zu koordinieren, unter den Parser und sicherzustellen, dass nur ein thread Zugriff auf den Ausgabe-stream, der während einer bestimmten Zeit:
Bezüglich Ihrer ersten Frage, Anmerkung, dass es wahrscheinlich der Fall, dass multi-threading bieten Sie keinen nutzen für Ihre jeweiligen Arbeitsauslastung. Es hängt davon ab, ob die Arbeit, die Sie tun, jeden Eingang (Ihre
ETL
- Funktion) ist in Erster Linie CPU-bound oder IO-bound. Falls ersteres (was ich vermute, ist wahrscheinlich), threads werden nicht helfen, weil der global interpreter lock. In diesem Fall würden Sie wollen, um diemultiprocessing
- Modul zum verteilen der Arbeit auf mehrere Prozesse statt mehrere threads.Aber Sie können die gleichen Ergebnisse mit einem einfacher zu implementieren, - workflow: teilen Sie die input-Datei in
n
Stücke (mit, z.B., dersplit
Befehl); aufrufen der extract-transform-Skript separat auf jede Subdatei; dann verketten Sie die Ausgabe-Dateien.Einen Fehler: "die Verwendung von standard-input zum Lesen der Daten Zeile für Zeile, weil es lädt nicht die gesamte Datei in den Speicher" um ein Missverständnis. Können Sie eine Datei Lesen und Zeile für Zeile innerhalb von Python durch, z.B., ersetzen
sys.stdin
mit einem file-Objekt in einem Konstrukt wie:Siehe auch die
readline()
- Methode der file-Objekte, und beachten Sie, dassread()
können als parameter die maximale Anzahl der zu lesenden bytes.InformationsquelleAutor Alp
Ob threading wird hilfreich sein, Sie ist stark abhängig von Ihrer situation. Insbesondere, wenn Ihr
ETL()
Funktion beinhaltet eine Menge Zugriff auf die Festplatte, dann einfädeln würden, dürfte Ihnen ziemlich erhebliche Verbesserung der Geschwindigkeit.In der Antwort zu Ihrer ersten Frage, ich habe immer gefunden, dass es gerade hängt. Es gibt eine Menge Faktoren spielen bei der Bestimmung der idealen Anzahl von threads, und viele von Ihnen sind Programm-abhängig. Wenn du tust, viel Zugriff auf die Festplatte (das ist ziemlich langsam), zum Beispiel, dann werden Sie wollen mehr threads zu nutzen, die Ausfallzeiten während der Wartezeit für Zugriff auf die Festplatte. Wenn das Programm die CPU-gebunden, obwohl, Tonnen von threads, die vielleicht nicht super hilfreich. So, während es vielleicht möglich ist, zu analysieren alle Faktoren, die eine ideale Anzahl der threads an, es ist in der Regel viel schneller zu machen, eine erste Vermutung, und passen Sie dann von dort.
Genauer gesagt, obwohl, ist die Zuweisung einer bestimmten Anzahl von Zeilen zu jedem thread ist wohl nicht der beste Weg zu gehen über divvying auf der Arbeit. Denken Sie zum Beispiel, wenn eine Zeile nimmt eine besonders lange Zeit zu verarbeiten. Am besten wäre es, wenn ein thread könnte die Arbeit Weg an, dass eine Zeile und die anderen threads konnte jeder noch ein paar Zeilen mehr in der Zwischenzeit. Der beste Weg, um dies zu umgehen, ist die Verwendung einer Warteschlange. Wenn Sie schieben Sie jede Zeile in eine Warteschlange, dann kann jeder thread, ziehen Sie eine Linie aus der Warteschlange, damit umgehen, und wiederholen Sie, bis die Warteschlange leer ist. Auf diese Weise, die Arbeit wird verteilt, so dass kein thread jemals ohne Arbeit zu tun (bis auf das Ende natürlich).
Nun, ist die zweite Frage. Du hast auf jeden Fall Recht, dass das schreiben auf stdout aus mehreren threads auf einmal nicht die ideale Lösung. Im Idealfall würden Sie die Dinge so anzuordnen, dass das schreiben auf stdout passiert in nur einem Ort. Eine große Weise, das zu tun, ist die Verwendung einer Warteschlange. Wenn Sie in jeden thread schreiben Ihre Ausgabe auf eine freigegebene Warteschlange, dann können Sie spawn-einen zusätzlichen thread, dessen einzige Aufgabe ist, ziehen Sie die Elemente aus, die Warteschlange und drucken Sie Sie auf stdout aus. Durch die Beschränkung der Druck auf nur eine threading, Sie vermeiden die Probleme, die inhärent in mehrere threads versuchen, zu drucken, auf einmal.
InformationsquelleAutor mculhane