我正在使用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)
将较大的任务分成较小的部分.
第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模型知识与数据库进行交互.这对你来说并不是一个真正的挑战 - 只要尝试一下大局的孤立任务,如果他们正在工作就把它们放在一起 - 祝你好运.
| 归档时间: |
|
| 查看次数: |
1108 次 |
| 最近记录: |