URL: https://linuxfr.org/users/m4rotte/journaux/analyse-de-texte Title: Analyse de texte Authors: Marotte ⛧ Date: 2015年12月15日T01:13:52+01:00 License: CC By-SA Tags: python, sqlite et taln Score: 13 Mon but est d’analyser la fréquence de syllabes ou de mots depuis différents textes. Les fréquences d’apparition de chaque mot/syllabe étant cumulées dans une base de données. À chaque fois que j’ai posté du code ici je n’ai reçu que des critiques constructives alors je vous soumets celui-là :) Le code fait ce que je lui demande mais il est très lent sur de gros textes. Je pense que le problème se situe dans mes interactions avec la base de données. J’ai ~~quelques~~ une idée pour remédier à ce problème, vous verrez plus bas, vous me donnerez peut-être votre avis. ```python3 #!/usr/bin/env python3 """Reader.py: Read text for strings frequency.""" __author__ = "M4rotte" __copyright__ = "Copyright 2015, Institut Marotte pour un Mouling de Qualitäy" __license__ = "GPL" __version__ = "0.1" import sys # SYS module (used for argument management) import re # Regular expressions import sqlite3 # SQLite import time # Time is something you've never have enough from collections import deque # Read buffer MAXLEN = 24 KEEPMAXLEN = 3 # Over this length we only keep strings which don't match following regexp to avoid too many splitted words reKEEP = re.compile(r'^( |[A-ZÉÀÔ])(.*)( |\n|\.|,|\;)$') buf = deque(['' for s in range(MAXLEN)]) counter = 0 string = '' strings = {} strings_ok = {} dbfile = './reader.sqlite' ### Read input and populate `strings{}` try: while True: c = sys.stdin.read(MAXLEN-1) if c: for i in range (0,len(c)): buf.popleft() buf.append(c[i]) #print(buf) for i in range (MAXLEN-len(c)-1, MAXLEN): string = '' for j in range (i, MAXLEN): try: #print("(i,j):"+str(i)+","+str(j)) if buf[i]: string += buf[j] s = string.replace ("\n"," ") string = s.replace(" "," ") if len(string)> 1: strings[string] += 1 #print ("ANOTHER:"+string) except KeyError: strings[string] = 1 #print ("NEW:"+string) #print(strings) counter += 1 else: break except KeyboardInterrupt as e: sys.stderr.write (repr(e)) sys.stderr.flush() sys.stdout.flush() exit(1) sys.stderr.write (str(counter) + "×ばつ"+ str(MAXLEN) + " bytes read.\n") sys.stderr.write (str(len(strings)) + "\traw strings.\n") ### Remove unwanted strings for s in strings: if len(s) < KEEPMAXLEN: strings_ok[s] = strings[s] elif reKEEP.match(s): strings_ok[s] = strings[s] #print(s) ### Free some memory buf.clear() strings.clear() sys.stderr.write (str(len(strings_ok)) + "\tOK strings.\n") # Open database connection = sqlite3.connect(dbfile) cursor = connection.cursor() # Create SQLite table if not exists, to store shits... cursor.execute('create table if not exists strings (string text primary key, freq int)') # Store `strings_ok{}` into database inserted = 0 updated = 0 for s in strings_ok: try: cursor.execute("insert into strings values (?, ?)",(s, strings_ok[s])) inserted += 1 except sqlite3.IntegrityError: updated += 1 cursor.execute("update strings set freq=freq+? where string like ?",(strings_ok[s],s)) if ((inserted+updated) % 100 == 0): prog = (inserted+updated)/len(strings_ok)*100 sys.stderr.write ("Database update: "+str(round(prog,1))+"%\r") sys.stderr.flush() print("Database update:\tOK. ") cursor.execute("select count(*) from strings") count = cursor.fetchone()[0] sys.stderr.write (str(inserted)+"\tstrings inserted in database.\n") sys.stderr.write (str(updated)+"\tstrings updated in database.\n") sys.stderr.write (str(count)+"\trecords in database.\n") connection.commit() connection.close() ``` Je pense que la grosse erreur se situe ici : ```python cursor.execute("update strings set freq=freq+? where string like ?",(strings_ok[s],s)) ``` ce doit être une requête coûteuse à cause de la clause _where_... Donc mon idée serait de reporter l’incrément des compteurs au niveau du code Python, ce qui ne nécessite qu’un _select_, puis de remplacer l’_update_ par un _insert or replace_...

AltStyle によって変換されたページ (->オリジナル) /