emulate file-like behavior in python
Question: I'm writing a script, where I have to dump some columns of tables from an SQL
database into a file, and transfer it via FTP.

Because dumps can get really big, my Idea was to write a FakeFile which querys
row by row from a cursor in its `readline` method and pass it to
`ftplib.FTP.storlines`.

This is what I have so far:

    
    
    import ftplib
    import MySQLdb
    
    def 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 along select ... FROM %s
            self.cursor.execute(query, table_name)
            self._has_written_index = False
            #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:
                ret = []
                for desc in self.cursor.description:
                    ret.append(desc[0])
                self._has_written_index = True
            else:
                ret = self.cursor.fetchone()
            if not ret:
                return None
    
            s = ""
            for col in ret:
                s += str(col) + self.delimeter
            return s + "\n"
    
        def readlines(self, size):
            ret = []
            line = self.readline()
            while line:
                ret.append(line)
                line = self.readline()
    
        def write(self, string):
            raise Exception("cannot write to a MySQLFakeFile")
    
        def writelines(self, lines)
            raise Exception("cannot write to a MySQLFakeFile")
    
    db = MySQLdb("host", "user", "pass", "db")
    ftp = ftplib.FTP("host", "user", "pass")
    fakeFile = MySQLFakeFile(db.cursor(), ";", "tableName", "SELECT * FROM %s")
    ftp.storlines("STOR tableName.csv", fakeFile)
    

gives me

    
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/lib/python2.7/ftplib.py", line 496, in storlines
        if len(buf) > self.maxline:
    TypeError: object of type 'NoneType' has no len()
    

What am I doing wrong, and whats the `NoneType` here?


Answer: Your readline returns `None` instead of empty string `""` when reached end-of-
rows.

Your readlines returns nothing.

    
    
    def readlines(self, size):
        ret = []
        while True:
            line = self.readline()
            if not line:
                break
            ret.append(line)
        return ret
    

