Django适配器CSV需要几个小时才能导入

Pro*_*eus 7 python django

我正在使用Django适配器上传一个简单的CSV.当我导入100或200个联系人时,它似乎工作得很好.但是当我尝试上传一个包含5000个联系人的165kb文件时,它永远不会完成.我让它继续尝试,当我在1小时后回来时它还在尝试.

这有什么问题?使用Django适配器导入165kb文件不可能花费一个多小时.代码有问题吗?

 def process(self):
        self.date_start_processing = timezone.now()
        try:


            # Try and import CSV
            ContactCSVModel.import_data(data=self.filepath, extra_fields=[
                {'value': self.group_id, 'position': 5},
                {'value': self.uploaded_by.id, 'position': 6}])

            self._mark_processed(self.num_records)
        except Exception as e:
            self._mark_failed(unicode(e))
Run Code Online (Sandbox Code Playgroud)

CsvModel

class ContactCSVModel(CsvModel):

    first_name = CharField()
    last_name = CharField()
    company = CharField()
    mobile = CharField()
    group = DjangoModelField(Group)
    contact_owner = DjangoModelField(User)


    class Meta:
        delimiter = "^"
        dbModel = Contact
        update = {'keys': ["mobile", "group"]}
Run Code Online (Sandbox Code Playgroud)

Sas*_*ied 7

将较大的任务分成较小的部分.

第1步 - 只需阅读CSV文件

ContactCSVModel.import_from_filename()和ContactCSVModel.import_from_file()都返回csv行.禁用与django模型的交互以跳过与数据库的交互.这应该会大大加快任务并打印导入的数据.这绝对有用!

CSVModel

class ContactCSVModel(CsvModel):

    first_name = CharField()
    last_name = CharField()
    company = CharField()
    mobile = CharField()
    group = DjangoModelField(Group)
    contact_owner = DjangoModelField(User)


    class Meta:
        delimiter = "^"
Run Code Online (Sandbox Code Playgroud)

你的代码

 def process(self):
        self.date_start_processing = timezone.now()
        try:


            # Try and import CSV
            lines = ContactCSVModel.import_data(data=self.filepath, extra_fields=[
                {'value': self.group_id, 'position': 5},
                {'value': self.uploaded_by.id, 'position': 6}])
            print lines # or use logging

            self._mark_processed(self.num_records)
        except Exception as e:
            self._mark_failed(unicode(e))
Run Code Online (Sandbox Code Playgroud)

第2步 - 启用django模型交互但禁用以检查数据库中的现有项目.

禁用它,因为启用此功能将查询数据库中CSV中的每一行,以根据您的自然密钥规范检查现有项目(我已阅读源代码).您可能知道CSV中的所有行都是唯一的联系人.

如果您的问题在整个导入期间是缓慢的数据库查询,这将有所帮助,但如果导入消耗太多内存,则无法提供帮助.

class ContactCSVModel(CsvModel):

    first_name = CharField()
    last_name = CharField()
    company = CharField()
    mobile = CharField()
    group = DjangoModelField(Group)
    contact_owner = DjangoModelField(User)


    class Meta:
        delimiter = "^"
        dbModel = Contact
Run Code Online (Sandbox Code Playgroud)

第3步 - 导入大小相同的CSV块

使用CSVModel并启用与Contact模型的交互,但为ContactCSVModel.import_data()提供较小的可迭代.我将其设置为500.根据您的需要进行更改.下面的代码示例(链接)是为了让您了解.您需要稍微更改它以将其放入现有代码中.如果内存消耗是问题,这将有所帮助.

import csv
reader = csv.reader(open(self.filepath, 'rb'))

def gen_chunks(reader, chunksize=100):
    """ 
    Chunk generator. Take a CSV `reader` and yield
    `chunksize` sized slices. 
    """
    chunk = []
    for i, line in enumerate(reader):
        if (i % chunksize == 0 and i > 0):
            yield chunk
            del chunk[:]
        chunk.append(line)
    yield chunk

for chunk in gen_chunks(reader, chunksize=500):
    ContactCSVModel.import_data(data=chunk, extra_fields=[
                {'value': self.group_id, 'position': 5},
                {'value': self.uploaded_by.id, 'position': 6}])
Run Code Online (Sandbox Code Playgroud)

第4步 - 针对大内存消耗和慢速操作

因为django-adapters在导入和慢速操作期间将所有Contact模型实例保存在内存中,因为多次单次提交而不是批量插入操作 - 它不适合较大的文件.

你有点绑定django-adapters.如果您依赖此django包,则无法切换到批量插入.使用任务管理器在Windows上用top或htop检查linux下的内存消耗.如果进程耗尽并且操作系统开始交换,请切换到另一个具有更高效内存消耗的django附加组件和批量插入作为选项 - 有很多用于csv导入.

另一个提示是使用csv模块进行读取,并使用django模型知识与数据库进行交互.这对你来说并不是一个真正的挑战 - 只要尝试一下大局的孤立任务,如果他们正在工作就把它们放在一起 - 祝你好运.