所以,我需要一些帮助才能使这个脚本运行得更快,下面是我的脚本。
#!/usr/bin/env python
import glob,os, csv
from sqlalchemy import *
count = 0
served_imsi = []
served_imei = []
served_msisdn = []
sgsn_address = []
ggsn_address = []
charging_id = []
apn_network = []
location_area_code = []
routing_area = []
cell_identity = []
service_area_code = []
s_charging_characteristics = []
plmn_id = []
path = '/home/cneps/cdr/*.cdr'
for file in glob.glob(path):
f = open(file)
for lines in f:
served_imsi.append(lines[17:17+16])
served_imei.append(lines[47:47+16])
served_msisdn.append(lines[65:65+18])
sgsn_address.append(lines[83:83+32])
ggsn_address.append(lines[115:115+32])
charging_id.append(lines[147:147+10])
apn_network.append(lines[157:157+63])
location_area_code.append(lines[296:296+4])
routing_area.append(lines[300:300+2])
cell_identity.append(lines[302:302+4])
service_area_code.append(lines[306:306+4])
s_charging_characteristics.append(lines[325:325+2])
plmn_id.append(lines[327:327+6])
db = create_engine('sqlite:///CDR.db',echo=False)
metadata = MetaData(db)
CDRS = Table('CDRS', metadata, autoload=True)
i = CDRS.insert()
while count < len(served_imei):
i.execute(Served_IMSI=served_imsi[count],
Served_IMEI=served_imei[count],
Served_MSISDN=served_msisdn[count],
SGSN_Address=sgsn_address[count],
GGSN_Address=ggsn_address[count],
Charging_ID=charging_id[count],
APN_Network=apn_network[count],
LAC=location_area_code[count],
RAC=routing_area[count],
Cell_Identity=cell_identity[count],
Service_Area_Code=service_area_code[count],
S_Charging_Characteristics=s_charging_characteristics[count],
PLMN_ID=plmn_id[count])
count += 1
for files in glob.glob(path):
os.remove(files)
代码很好。但是我花了太长时间,我问了一位朋友,他建议使用session.add来加快速度。
我带来的解决方案是这样的:
for item in lists:
session.add(item)
但这只适用于一个列表,我有14个列表。
有没有人知道如何将session.add实现到我的代码中,而不是执行?
谢谢!
答案 0 :(得分:1)
有两种(主要)方法可以使用SQLAlchemy。您目前正在使用SQLAlchemy Expression Language API的方式。使用session.Add
是Object Relational API的一部分。它们有两个不同的用途,我建议阅读一些文档来了解差异。
对象关系API(通常称为ORM或“对象关系映射器”)使用下面的SQLAlchemy表达式语言,因此您可以在SQLAlchemy Expression API中执行ORM API中的任何操作(虽然语法不同)。所以,我建议除非你真的需要,否则不要试图将代码转换到其他API。
作为完全重写代码的替代方法,请注意您这样做:
CDRS = Table('CDRS', metadata, autoload=True)
i = CDRS.insert()
i
成为insert expression。您可以使用它来动态创建插入语句。您可以通过打印i
来尝试这一点:它看起来像带有参数的SQL字符串(但请注意,该值实际上不是字符串;它是一个帮助自动创建SQL字符串的对象)。将该插入对象传递给execute
方法(以及所有参数)时,生成的SQL字符串将被执行。
现在,您正在使用insert语句的execute方法。首选方法是在引擎上使用execute方法。所以,而不是......
i.execute(...)
......你应该......
db.execute(i, ...)
性能问题是您遇到涉及每行使用execute
一次的问题。因此,每个INSERT都在自己的事务中运行,这可能很慢。你可以做点像......
all_data = []
while count < len(served_imei):
data = {
'Served_IMSI' : served_imsi[count],
'Served_IMEI' : served_imei[count],
...
}
all_data.append(data)
count += 1
现在,all_data
包含一个字典列表,每个字典包含insert语句的键(列名)和值(列值)。然后,你可以使用......
db.execute(i, all_data)
我建议您在开展此工作时启用echo
以了解SQLAlchemy正在做什么:
db = create_engine('sqlite:///CDR.db',echo=True) # Change `echo` from False to True
你的下一步是删除你的两个循环,并创建我刚刚从代码中从文件中读取的部分显示的字典。例如:
#!/usr/bin/env python
import glob,os, csv
from sqlalchemy import *
db = create_engine('sqlite:///CDR.db',echo=False)
metadata = MetaData(db)
CDRS = Table('CDRS', metadata, autoload=True)
insert_statement = CDRS.insert()
all_data = []
path = '/home/cneps/cdr/*.cdr'
for file in glob.glob(path):
# Use "with" to automatically close "f" when we're done with it.
with open(file) as f:
for lines in f:
d = {
'Served_IMSI' : lines[17:17+16],
....
}
all_data.append(d)
# No need for that "while count < len(served_imei)" loop, we can now just do...
db.execute(insert_statement, all_data)
答案 1 :(得分:0)
我会创建一个类,例如。 CDRItem喜欢:
class CDRItem(db.Session):
def __init__(served_imsi ....):
served_imsi = self.served_imsi
等等。 然后我将遍历cdr的行,创建新的CDRItem类对象并将它们放入列表中 列表创建后,剩下的就是
session.add_all(created_list)