Voici mon script pour effectuer un traitement de texte simple à partir d'environ 21 fichiers de log, chacun d'environ 300 KB à 1 MB (maximum) x 5 fois répété (total de 125 fichiers, en raison de la journal répété 5 fois).
Code Python (le code a été modifié pour utiliser le code compilé re
et en utilisant re.I
)
#!/usr/bin/python
import re
import fileinput
exists_re = re.compile(r'^(.*?) INFO.*Such a record already exists', re.I)
location_re = re.compile(r'^AwbLocation (.*?) insert into', re.I)
for line in fileinput.input():
fn = fileinput.filename()
currline = line.rstrip()
mprev = exists_re.search(currline)
if(mprev):
xlogtime = mprev.group(1)
mcurr = location_re.search(currline)
if(mcurr):
print fn, xlogtime, mcurr.group(1)
Code Perl
#!/usr/bin/perl
while (<>) {
chomp;
if (m/^(.*?) INFO.*Such a record already exists/i) {
$xlogtime = $1;
}
if (m/^AwbLocation (.*?) insert into/i) {
print "$ARGV $xlogtime $1\n";
}
}
Et, sur mon PC, les deux codes génèrent exactement le même fichier de résultat de 10 790 lignes. Et, voici le chronométrage effectué sur les implémentations Perl et Python de Cygwin.
User@UserHP /cygdrive/d/tmp/Clipboard
# time /tmp/scripts/python/afs/process_file.py *log* *log* *log* *log* *log* >
summarypy.log
real 0m8.185s
user 0m8.018s
sys 0m0.092s
User@UserHP /cygdrive/d/tmp/Clipboard
# time /tmp/scripts/python/afs/process_file.pl *log* *log* *log* *log* *log* >
summarypl.log
real 0m1.481s
user 0m1.294s
sys 0m0.124s
À l'origine, il fallait 10,2 secondes avec Python et seulement 1,9 seconde avec Perl pour ce simple traitement de texte.
(UPDATE) mais, après la compilation de l re
version de Python, il faut maintenant 8,2 secondes en Python et 1,5 seconde en Perl. Perl est tout de même beaucoup plus rapide.
Existe-t-il un moyen d'améliorer la vitesse de Python OU il est évident que Perl sera le plus rapide pour le traitement de texte simple.
D'ailleurs, ce n'est pas le seul test que j'ai fait pour un simple traitement de texte... Et, chaque fois que je fais le code source d'une manière différente, Perl gagne toujours de loin. Et, pas une seule fois Python n'a été plus performant pour un simple m/regex/
correspondre et imprimer des trucs.
Ne suggérez pas l'utilisation de C, C++, Assembly, ou d'autres variantes de Python, etc.
Je cherche une solution en utilisant Python standard avec ses fonctions intégrées modules intégrés par rapport à Perl standard (sans même utiliser les modules). Mon garçon, je souhaite utiliser Python pour toutes mes tâches en raison de sa lisibilité, mais renoncer à la vitesse, je ne le pense pas.
Donc, s'il vous plaît, suggérez comment le code peut être amélioré pour avoir des données comparables. résultats comparables à ceux de Perl.
MISE À JOUR : 2012-10-18
Comme d'autres utilisateurs l'ont suggéré, Perl a sa place et Python la sienne.
Ainsi, pour cette question, on peut conclure sans risque que pour une simple correspondance regex sur chaque ligne pour des centaines ou des milliers de fichiers texte et l'écriture des résultats dans un fichier (ou l'impression à l'écran), Perl gagnera toujours, toujours, en performance pour ce travail. C'est aussi simple que cela.
Veuillez noter que lorsque je dis que Perl gagne en performance... seuls Perl et Python standard sont comparés... sans recourir à certains modules obscurs (obscurs pour un utilisateur normal comme moi) et sans appeler les bibliothèques C, C++, assembly depuis Python ou Perl. Nous n'avons pas le temps d'apprendre toutes ces étapes et installations supplémentaires pour un simple travail de correspondance de texte.
Donc, Perl est excellent pour le traitement de texte et les regex.
Python a sa place pour faire du rock dans d'autres endroits.
Mise à jour 2013-05-29 : Un excellent article qui fait une comparaison similaire est ici . Perl l'emporte à nouveau pour la correspondance de texte simple... Et pour plus de détails, lisez l'article.
0 votes
Les motifs sont-ils compilés une seule fois en Python (comme en Perl) ?
0 votes
Les deux programmes sont-ils équivalents ? Je ne vois rien comme /i dans la version Python.
0 votes
Ils ne sont pas totalement équivalents (
(?i)
ore.I
devrait être ajouté pour Python), mais très proche.1 votes
Je me demande si la différence réside dans le temps passé à revenir en arrière dans les lignes qui ne correspondent pas.
0 votes
J'ai édité le code pour compiler le re et utiliser le re.I. Benchmarking à nouveau et j'ai mis à jour les résultats dans ma question.
0 votes
Il serait également bon de connaître les versions de Perl et de Python (le x pour 2.x). Le site
line.rstrip()
n'est pas nécessaire.0 votes
@ihightower : Quels sont les arguments exacts passés au script ? Sont-ils vraiment
*log* *log* *log* *log* *log*
? Si oui, êtes-vous sûr que Perl n'extrait pas uniquement les noms de fichiers uniques ? (Ce qui fait qu'il traite en fait moins de fichiers...)0 votes
@pepr, Perl traitera tous les fichiers.
0 votes
Vous pouvez probablement accélérer les deux versions un tout petit peu en utilisant
/s
.3 votes
J'ai fait passer le code Python dans un fichier Profileur pour découvrir où il passe son temps. Vous pouvez également essayer d'utiliser PCRE (Expressions régulières compatibles avec Perl) plutôt que les regex intégrés à Python (voir ci-dessous). une autre application ) et voir si cela donne de meilleurs résultats.
3 votes
"Fermé car trop localisé" me semble trop drôle et subjectif.
1 votes
J'ai déjà vu des benchmarsk qui suggèrent que l'implémentation regexp de Perl est juste beaucoup plus rapide que Python. Sinon, ils devraient être d'une vitesse comparable.
0 votes
La recherche répétée de fonctions en Python peut prendre un temps surprenant lors de longues boucles. Vous devriez donc utiliser exists_re = re.compile(...).search, et ensuite appeler exists_re(currline) dans votre boucle (et quelque chose de similaire pour location_re). Vous devriez également déplacer fn = fileinput.filename() en dehors de la boucle qui effectue vos itérations de lignes, bien que pour cela, vous devriez probablement arrêter d'utiliser fileinput. Puisque vos deux regex correspondent au début de la ligne, vous pourriez aussi essayer de passer à re.match au lieu de re.search.
0 votes
Au cas où quelqu'un voudrait voir, quelques résultats ici
0 votes
Vous devriez le vérifier une fois de plus puisque python a été mis à jour en 2.8.9 à partir de 2.4.4
0 votes
J'ai lu que re2 implémenté par Google est meilleur. Je l'ai essayé mais aucune amélioration : re (4.5 sec), re2 (4.5 sec), perl (0.8 sec)
0 votes
Vous pourriez probablement accélérer les deux versions en utilisant elsif... Sauf si ces deux regex peuvent correspondre à la même ligne.
0 votes
En Python, lorsque vous effectuez un filtrage avec le début de la chaîne (
r"^..."
) n'utilisent paspattern.search()
utiliser la méthodepattern.match
à la place, ce qui est un peu plus rapide.