我想通过FTP将数据转储到远程服务器。因为转储可能变得非常大,我的想法是编写一个FakeFile,它根据需要转储行,并在readline中逐个返回。
这是我的MySQLFakeFile:
class MySQLFakeFile(object):
'''
Simulates a read-only file, which dumps rows on demand.
Use this, to pass it to the FTP protocol to make the dump more efficient,
without the need to dump it somewhere and copy it over the net afterwords
'''
def __init__(self, cursor, delimeter, table_name, query):
self.cursor = cursor
self.delimeter = delimeter
self.table_name = table_name
#query is something like 'SELECT * FROM %s'
self.cursor.execute(query, table_name)
self._has_written_index = False
self.rest = None
#file attrs
self.closed = False
self.name = table_name + ".csv"
self.encoding = "utf-8"
self.mode = "r"
def close(self):
self.cursor.close()
self.closed = True
def flush(self):
'''No-OP'''
pass
def read(self, size):
pass
def readline(self, size):
if not self._has_written_index:
logging.debug("not written index! write Index")
ret = []
for desc in self.cursor.description:
ret.append(desc[0])
self._has_written_index = True
elif self.rest:
s = self.rest
self.rest = None
else:
ret = self.cursor.fetchone()
if not ret:
return ""
if not self.rest:
s = ""
for col in ret:
s += str(col) + self.delimeter
if len(s) > size:
s, self.rest = s[:size-1], s[size-1:]
return s + "\n"
def readlines(self, size):
ret = []
line = self.readline(size)
while line:
ret.append(line)
line = self.readline(size)
def write(self, string):
raise Exception("cannot write to a MySQLFakeFile")
def writelines(self, lines):
raise Exception("cannot write to a MySQLFakeFile")
如果我将其传递给其stornline
方法内的FTP实例,它会将所有内容写入最后一行,然后返回一个空字符串并挂起此函数,
(第545行conn.unwrap()
)
如果我查看ftplib source,它会因第535行if not buf: break
而中断。
挂起后,我在远程服务器上查看该文件是否完全存在。
我做错了什么,以及阻止conn.unwrap
返回的原因?