2010-11-27 9 views
1

Je lance un script de conversion qui envoie de grandes quantités de données à un db en utilisant l'ORM de Django. J'utilise la validation manuelle pour accélérer le processus. J'ai des centaines de fichiers à valider, chaque fichier va créer plus d'un million d'objets. J'utilise Windows 7 64bit. J'utilise Windows 7 64bit. J'ai remarqué que le processus Python ne cesse de croître jusqu'à ce qu'il consomme plus de 800 Mo, et ce n'est que pour le premier fichier!Le processus Python ne cesse de croître dans le script django db upload

Le script boucle sur les enregistrements dans un fichier texte, réutilisant les mêmes variables et sans accumulation de listes ou de tuples.

Je lis here que c'est un problème général pour Python (et peut-être pour tout programme), mais j'espérais peut-être Django ou Python a une certaine façon explicite de réduire la taille du processus ...

Voici un aperçu du code:

import sys,os 
sys.path.append(r'D:\MyProject') 
os.environ['DJANGO_SETTINGS_MODULE']='my_project.settings' 
from django.core.management import setup_environ 
from convert_to_db import settings 
from convert_to_db.convert.models import Model1, Model2, Model3 
setup_environ(settings) 
from django.db import transaction 

@transaction.commit_manually 
def process_file(filename): 
    data_file = open(filename,'r') 

    model1, created = Model1.objects.get_or_create([some condition]) 
    if created: 
     option.save() 

    while 1: 
     line = data_file.readline() 
     if line == '': 
      break 
     if not(input_row_i%5000): 
      transaction.commit() 
     line = line[:-1] # remove \n 
     elements = line.split(',') 

     d0 = elements[0] 
     d1 = elements[1] 
     d2 = elements[2] 

     model2, created = Model2.objects.get_or_create([some condition]) 
     if created: 
      option.save() 

     model3 = Model3(d0=d0, d1=d1, d2=d2) 
     model3 .save() 

    data_file.close() 
    transaction.commit() 

# Some code that calls process_file() per file 

Répondre

3

Première chose, assurez-vous DEBUG=False dans votre settings.py. Toutes les requêtes envoyées à la base de données sont stockées dans django.db.connection.queries lorsque DEBUG=True. Cela deviendra une grande quantité de mémoire si vous importez de nombreux enregistrements. Vous pouvez le vérifier via le shell:

$ ./manage.py shell 
> from django.conf import settings 
> settings.DEBUG 
True 
> settings.DEBUG=False 
> # django.db.connection.queries will now remain empty/[] 

Si cela ne pas essayer alors frayer un nouveau Process pour exécuter process_file pour chaque fichier. Ce n'est pas le plus efficace, mais vous essayez de réduire l'utilisation de la mémoire et non les cycles du processeur. Quelque chose comme ça devrait vous aider à démarrer:

from multiprocessing import Process 

for filename in files_to_process: 
    p = Process(target=process_file, args=(filename,)) 
    p.start() 
    p.join() 
+0

Vous aviez absolument raison! Dans ma première course le processus a fini par être plus de 1 Go en mémoire. Une fois que j'ai défini DEBUG sur False, le processus est resté 13 Mo tout au long du script. Merci! – Jonathan

0

Il est difficile de dire ce que je propose est le profil de votre code & voir quelle partie de votre code est à l'origine de cette montée subite de la mémoire. Une fois que vous savez quelle partie du code est en mémoire, vous pouvez penser à la réduire. - Même si vos efforts n'entraînent pas une diminution de la consommation de mémoire, vous pouvez le faire - Comme les processus obtiennent une allocation mémoire en morceaux (ou pages) & en les relâchant alors que le processus est encore en cours, vous pouvez générer un processus fils. faites toutes vos tâches intensives en mémoire là & passez les résultats au processus parent & die. De cette façon, la mémoire consommée (du processus enfant) est renvoyée le système d'exploitation & votre processus parent reste maigre ...