【问题标题】:Python / Django compare and update model objectsPython / Django 比较和更新模型对象
【发布时间】:2018-01-14 09:41:51
【问题描述】:

我才刚开始使用 python,但在过去的几个月里学到了很多东西,现在我在快速更新模型上的对象方面遇到了困难。

我有一个名为 Products 的模型,它是从一个 csv 文件中填充的,每天这个文件都会随着成本和数量等变化而更新,我可以将文件的每一行与 Products 模型进行比较,但是这需要 120k 行3-4 小时。

我可以采取什么过程来使这个过程更快地处理这个文件。如果成本和数量发生变化,我只想修改对象

任何建议我如何解决这个问题?

我尝试过的版本 3。

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

【问题讨论】:

  • 我们如何提高我们从未见过的代码的效率?发布你所做的,让我们看看哪里错了
  • 您可以使用散列快速比较两个对象的差异。您可以使用它来加速对象比较。另一种方法是比较每天的 csv 文件并仅提取已更改以进行更新的行。
  • 120k lines this takes 3-4hours. 你当然期待太多了。不能花这么多时间。如果您要处理的数据多于我建议使用诸如 celery 之类的任务运行器。

标签: python django csv multiprocessing


【解决方案1】:

我曾经遇到过数据加载缓慢的问题,我可以告诉你我做了什么也许它可以以某种方式帮助你,我将执行传递到调试模式并试图找出导致加载缓慢的列,并且每次我看到一个列导致问题时,我都会在其上添加一个索引(在我的情况下,在 SGBD --> postgreSQL 中),并且它起作用了。我希望你也面临同样的问题,所以我的回答可以帮助你。

【讨论】:

    【解决方案2】:

    这是一个粗略的想法: 1,读取csv时,使用@BearBrow建议的pandas到array_csv 2、将Django中的obj数据转换成Numpy数组array_obj 3、不要一一比较,使用numpy减法

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

    4、找到更新的列 obj_need_updated = array_obj[np.logic_any(compare_index['cost'], compare['quantity'])]

    然后使用Django批量更新https://github.com/aykut/django-bulk-update进行批量更新

    希望这将为您提供加快代码速度的提示

    【讨论】:

    • 试一试。但得到一个错误。 code def get_file(): with zipfile.ZipFile(FILE_LOCATION + 'incoming/' + FILE_NAME, 'r') as zip: with zip.open('228688 .csv') as csvfile: list_in = pd.read_csv(csvfile ) print(list_in) pandas.errors.ParserError:数据标记错误。 C 错误:预计第 33967 行中有 40 个字段,看到 41
    • @fuel 好像228688.csv中的数据不一致,可以查看第33967行,错误说该行有41个字段,而另一行有40个字段
    • 所以我现在都在数组中,只需要学习如何比较每个产品代码的不同字段。
    • @fuel 如果你需要比较的字段是数字或浮点数,numpy 序列可以很容易地通过减法批量比较它们,然后找到零行及其行号。我建议你可以只用介绍文档来练习 numpy :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-28
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 2017-03-30
    • 1970-01-01
    • 2022-10-14
    相关资源
    最近更新 更多