Python Filetage stdin/stdout
J'ai un fichier qui contient beaucoup de données. Chaque ligne est un enregistrement. Et je suis en train de faire quelques ETL à l'encontre de l'ensemble du fichier. Maintenant je suis à l'aide de l'entrée standard pour lire les données ligne par ligne. La chose cool à propos de ce est votre script peut être très flexible pour s'intégrer avec d'autres scripts et des commandes du shell. J'ai écrit le résultat sur la sortie standard. Par exemple.
$ cat input_file
line1
line2
line3
line4
...
Mon code python ressemble à ceci - 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
Le code ci-dessous est de savoir comment il fonctionne maintenant:
cat input_file | python parse.py > output_file
J'ai regardé le Filetage module de Python et je me demande si le rendement est amélioré de façon spectaculaire si j'utilise ce module.
Question1: Comment dois-je planifier les quotas pour chaque thread, pourquoi?
...
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: Plusieurs Threads peuvent s'imprimer le résultat sur la sortie standard stdout dans le même temps, la façon de les organiser et d'éviter la situation ci-dessous?
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()
La sortie est vraiment laid, où une ligne contient les résultats de deux threads.
aFinished
cFinishedeFinished
bFinished
fFinished
dFinished
OriginalL'auteur B.Mr.W. | 2013-08-21
Vous devez vous connecter pour publier un commentaire.
De prendre votre deuxième question, c'est ce que mutex sont pour. Vous pouvez obtenir le nettoyeur de sortie que vous souhaitez à l'aide d'un verrou pour assurer la coordination entre les analyseurs et de s'assurer qu'un seul thread a accès au flux de sortie pendant une période de temps donnée:
En ce qui concerne votre première question, remarque que c'est probablement le cas que le multi-threading n'apportera aucun avantage pour votre charge de travail. Elle dépend en grande partie sur si le travail que vous faites avec chaque ligne de saisie (votre
ETL
fonction) est principalement lié au PROCESSEUR ou IO-lié. Si l'ancien (ce qui je pense est probable), les threads ne vous sera d'aucune aide, en raison de la mondial interprète de verrouillage. Dans ce cas, vous pouvez utiliser lamultiprocessing
module de répartir le travail entre plusieurs processus au lieu de plusieurs threads.Mais vous pouvez obtenir le même résultat avec un plus facile à mettre en œuvre des flux de travail: Diviser le fichier en entrée, en
n
morceaux (à l'aide, par exemple, lasplit
de commande); invoquer l'extrait-et-script de transformation séparément sur chaque sous-fichier; puis concaténer le résultat de fichiers.On pinaille: "à l'aide de l'entrée standard pour lire les données ligne par ligne car il ne sera pas charger tout le fichier en mémoire" implique une idée fausse. Vous pouvez lire un fichier ligne par ligne à partir de l'intérieur de Python, par exemple, le remplacement de
sys.stdin
avec un fichier objet dans une construction comme:Voir aussi la
readline()
méthode de fichiers objets, et note queread()
peut prendre en paramètre le nombre maximum d'octets à lire.OriginalL'auteur Alp
Si le filetage sera utile vous est fortement dépendant de votre situation. En particulier, si votre
ETL()
fonction implique beaucoup d'accès disque, puis le filetage serait susceptible de vous donner assez importante amélioration de la vitesse.En réponse à votre première question, j'ai toujours trouvé que cela dépend. Il y a beaucoup de facteurs qui entrent en jeu au moment de déterminer le nombre idéal de threads, et beaucoup d'entre eux sont dépendant du programme. Si vous faites beaucoup d'accès disque (ce qui est assez lent), par exemple, alors vous aurez envie plus de threads pour profiter des temps d'arrêt lors de l'attente pour l'accès au disque. Si le programme est lié au PROCESSEUR, bien que, des tonnes de threads peuvent pas être super utile. Ainsi, même s'il peut être possible d'analyser tous les facteurs de venir avec un nombre idéal de threads, il est généralement beaucoup plus rapide de faire une supposition initiale, puis ajuster à partir de là.
Plus précisément, l'attribution d'un certain nombre de lignes pour chaque thread n'est probablement pas la meilleure façon d'aller sur divvying de l'œuvre. Considérons, par exemple, si une ligne prend beaucoup de temps à traiter. Il serait mieux si un thread pourrait travailler loin à cette ligne et les autres threads peuvent faire un peu plus de lignes dans l'intervalle. La meilleure façon de gérer cela est d'utiliser une File d'attente. Si vous poussez chaque ligne dans une File d'attente, puis chaque thread peut tirer une ligne de la File d'attente, le manipuler, et répétez jusqu'à ce que la File d'attente est vide. De cette façon, le travail est distribuée telle qu'aucun fil ne soit jamais sans travail à faire (jusqu'à la fin, bien sûr).
Maintenant, à la seconde question. Vous avez bien raison que l'écriture sur la sortie standard (stdout) à partir de plusieurs threads à la fois, n'est-ce pas une solution idéale. Idéalement, il vous faudrait arranger les choses pour que l'écriture sur la sortie standard stdout qui se passe en un seul lieu. Une excellente façon de le faire est d'utiliser une File d'attente. Si vous avez chaque thread écrire sa sortie à une File d'attente partagée, alors vous pouvez vous frayer un thread supplémentaire dont la seule tâche est de tirer des éléments de la File d'attente et de les imprimer sur la sortie standard stdout. En limitant l'impression de juste un enfilage, vous aurez à éviter les problèmes inhérents à plusieurs threads tentent d'imprimer à la fois.
OriginalL'auteur mculhane