2017-08-07 6 views
0

Iv vient juste de commencer python mais j'ai beaucoup appris au cours des derniers mois, maintenant j'ai frappé un mur à propos de la mise à jour des objets sur un modèle à bonne vitesse. J'ai un modèle appelé Products et ceci est rempli à partir d'un fichier csv, chaque jour ce fichier est mis à jour avec des changements comme le coût, et la quantité, je peux comparer chaque ligne du fichier avec le modèle Products mais ayant 120k lignes this prend 3-4 heures.Python/Django comparer et mettre à jour des objets modèles

Quel processus puis-je prendre pour rendre ce processus ce fichier plus rapidement. Je veux seulement modifier les objets si le coût et la quantité ont changé

Des suggestions comment je m'attaque à cela?

Ver3 de ce que j'ai essayé.

from django.core.management import BaseCommand 
from multiprocessing import Pool 
from django.contrib.auth.models import User 
from pprint import pprint 
from CentralControl.models import Product, Supplier 
from CentralControl.management.helpers.map_ingram import * 
from CentralControl.management.helpers.helper_generic import * 
from tqdm import tqdm 

from CentralControl.management.helpers.config import get_ingram 
import os, sys, csv, zipfile, CentralControl 

# Run Script as 'SYSTEM' 
user = User.objects.get(id=1) 

# Get Connection config. 
SUPPLIER_CODE, FILE_LOCATION, FILE_NAME = get_ingram() 


class Command(BaseCommand): 
def handle(self, *args, **options): 
    list_in = get_file() 
    list_current = get_current_list() 

    pool = Pool(6) 

    pool.map(compare_lists(list_in, list_current)) 

    pool.close() 



def compare_lists(list_in, list_current): 
    for row_current in tqdm(list_current): 
     for row_in in list_in: 
      if row_in['order_code'] == row_current['order_code']: 

       #do more stuff here. 

       pass 

def get_current_list(): 
    try: 
     supplier = Supplier.objects.get(code='440040') 
     current_list = Product.objects.filter(supplier=supplier).values() 
     return current_list 
    except: 
     print('Error no products with supplier') 
     exit() 


def get_file(): 
    with zipfile.ZipFile(FILE_LOCATION + 'incoming/' + FILE_NAME, 'r') as zip: 
    with zip.open('228688 .csv') as csvfile: 
     reader = csv.DictReader(csvfile) 
     list_in = (list(reader)) 

     for row in tqdm(list_in): 
      row['order_code'] = row.pop('Ingram Part Number') 
      row['order_code'] = (row['order_code']).lstrip("0") 
      row['name'] = row.pop('Ingram Part Description') 
      row['description'] = row.pop('Material Long Description') 
      row['mpn'] = row.pop('Vendor Part Number') 
      row['gtin'] = row.pop('EANUPC Code') 
      row['nett_cost'] = row.pop('Customer Price') 
      row['retail_price'] = row.pop('Retail Price') 
      row['qty_at_supplier'] = row.pop('Available Quantity') 
      row['backorder_date'] = row.pop('Backlog ETA') 
      row['backorder_date'] = (row['backorder_date']) 
      row['backorder_qty'] = row.pop('Backlog Information') 

     zip.close() 
     #commented out for dev precess. 
     #os.rename(FILE_LOCATION + 'incoming/' + FILE_NAME, FILE_LOCATION + 'processed/' + FILE_NAME) 
     return list_in 
+1

Comment pouvons-nous améliorer l'efficacité du code que nous n'avons jamais vu? Publiez ce que vous avez fait et voyons où est le problème –

+0

Vous pouvez utiliser le hachage pour comparer rapidement deux objets à des différences. Vous pouvez l'utiliser pour accélérer la comparaison d'objets. Une alternative serait de comparer chaque jour le fichier csv et d'extraire uniquement les lignes qui ont changé pour la mise à jour. – pypypy

+0

'120k lignes cela prend 3-4 heures. Vous attendez certainement trop. Cela ne peut pas prendre autant de temps. Si vous avez tellement de données à traiter que je suggérerais d'utiliser des coureurs de tâches comme le céleri. –

Répondre

0

J'ai une fois face à un problème de charge lente des données, je peux vous dire ce que je ne peut-être il peut vous aider en quelque sorte, je suis passé à l'exécution en mode débogage et ai essayé de savoir Wich colomn est à l'origine de la chargement lent, et chaque fois que je vois qu'un colomn est à l'origine du problème, je lui ajoute un index (dans le SGBD -> postgreSQL dans mon cas), et cela a fonctionné. J'espère que vous faites face au même problème, alors ma réponse peut vous aider.

0

Ici, il est vague idée: 1, lors de la lecture csv, utilisez pandas géants comme suggèrent par @BearBrow dans array_csv 2, convertir les données obj de Django en Numpy arrary array_obj 3, ne les compare pas un par un, en utilisant soustractions numpy

compare_index = (array_csv[['cost',['quantity']]] - array[['cost',['quantity']]] == 0) 

4, trouver la colonne mise à jour obj_need_updated = array_obj [np.logic_any (compare_index [ 'coût'], comparer [ 'quantité'])]

puis utilisez la mise à jour en vrac Django https://github.com/aykut/django-bulk-update mettre à jour en bloc

Espérons que cela vous donnera des conseils pour accélérer votre code

+0

Donner une fissure. mais obtenir une erreur. 'recueil HSC def get_file(): avec zipfile.ZipFile (FILE_LOCATION + 'entrée /' + FILE_NAME, 'r') comme zip: avec zip.open ('228688 Csv') comme csvfile: list_in = pd.read_csv (csvfile) print (list_in) pandas.errors.ParserError: Erreur de segmentation des données. C erreur: prévu 40 champs dans la ligne 33967, vu 41 – flammable

+0

@ inflammable il semble que les données dans 228688.csv ne sont pas compatibles, vous pouvez vérifier la ligne 33967, l'erreur dit que la ligne a 41 champs tandis que l'autre ligne a 40 champs – wllbll

+0

Ouais J'ai lu à ce sujet et ajouté error_bad_lines = False. :) – flammable