我有一个程序可以从 CSV 文件或数据库中读取对象(任务)。这两个来源的共同点是您必须在使用资源后明确关闭对资源的访问。
我遵循使 CSV 和 DB 类都可迭代的方法,因此迭代它们会返回任务。这对于使用它们很方便,但是我不相信它是干净的,并且我有以下问题:
- 访问文件或数据库的最佳方法是什么?我为此使用构造函数,但我不确定多线程等...
- 关闭资源(文件,光标)的最佳方法是什么。外部对象是否应该通知访问完成,或者 CSV 或 DB 对象是否应该检测到我们位于文件末尾并关闭它?
我不确定我做对了(它适用于单次运行,但我的意思是这要插入网站,因此可以进行多次访问)
class CSV(AbstractDAO):
def __init__(self, sourcePath):
self.sourcePath = sourcePath
self.csvFile = codecs.open(sourcePath, 'rb', 'UTF-8')
def __iter__(self):
return self
def next(self):
return self._buildTaskFromLine(self.csvFile.next())
def deleteAllTasks(self):
pass
def loadTask(self, taskID):
csvFile = codecs.open(self.sourcePath, 'rb', 'UTF-8')
for line in csvFile:
taskValues = line.split(";")
if taskValues[0] == unicode(taskID):
return self._buildTaskFromLine(line)
else:
return None
def saveTask(self, task):
pass
def loadPredecessorsID(self, task):
csv = codecs.open(self.sourcePath, 'rb', 'UTF-8')
for line in csv:
taskValues = line.split(";")
if taskValues[0] == unicode(task.id):
return taskValues[2].split(",")
return None
def _buildTaskFromLine(self, line):
taskValues = line.split(";")
taskID = taskValues[0]
taskName = taskValues[1]
taskAncestors = taskValues[2]
taskDuration = int(taskValues[3])
return Task(taskID, taskName, taskDuration)
这是数据库实现
class SQLite(AbstractDAO):
def __init__(self, sourcePath):
self.connection = sqlite3.connect(sourcePath)
self.cursor = None
def __iter__(self):
self.cursor = self.connection.cursor()
self.cursor.execute("select * from Tasks")
return self
def next(self):
if self.cursor is not None:
row = self.cursor.fetchone()
if row is None:
self.cursor.close()
raise StopIteration
else:
return self._buildTaskFromRow(row)
def deleteAllTasks(self):
cursor = self.connection.cursor()
cursor.execute("delete from Tasks")
self.connection.commit()
cursor.close()
def loadTask(self, id):
cursor = self.connection.cursor()
param = (id,)
cursor.execute("select * from Tasks t where t.id = ? ", param)
taskRow = cursor.fetchone()
task = self._buildTaskFromRow(taskRow)
cursor.close()
return task
def saveTask(self, task):
cursor = self.connection.cursor()
param = (task.id,)
cursor.execute("select * from Tasks t where t.id = ? ", param)
taskRow = cursor.fetchone()
if taskRow is None:
param = (task.id, task.name, task.duration)
cursor.execute("insert into Tasks values (?,?,?)", param)
self.connection.commit()
cursor.close()
else:
param = (task.id, task.name, task.duration)
cursor.execute("update Tasks \
set description = ?, duration = ? \
where id = ? ", param)
self.connection.commit()
cursor.close()
def loadPredecessors(self, task):
pass
def _buildTaskFromRow(self, row):
taskId = row[0]
taskName = row[1]
taskDuration = row[2]
return Task(taskId, taskName, taskDuration)
最后,上面的代码例如被 ma TaskTree 这样调用(它是一个包含所有任务的对象)
def loadTreeFrom(self, source, sourcePath):
if source not in ('CSV', 'DB'):
raise AttributeError('Unknown source : supported sources are CSV or DB')
dao = None
if source == 'CSV':
dao = CSV(sourcePath)
elif source == "DB":
dao = SQLite(sourcePath)
#populate the tasks first
for task in dao:
self.tasks[unicode(task.id)] = task
# then populate the dependencies
for item in self.tasks.iteritems():
ancestorsID = dao.loadPredecessorsID(item[1])
self.addDependencies(item[1], ancestorsID)