Welcome, guest | Sign In | My Account | Store | Cart

Sometimes you have a file-like object (such as what urllib.urlopen() returns), but you need to pass it to a function/method that insists on receiving a true file object (what the file or open built-in functions give you). What you need is a adapter to turn your file-like object into a true file object.

Python, 42 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import types
import os

class FileAdaptor:
    """A FileAdaptor instance takes a 'file-like' object having at
    least a 'read' method and, via the file method, returns a true file
    object."""
    def __init__(self, fileObj):
        self.fileObj = fileObj
        self.chunksize = 1024 * 10

        # If the input file-like object is actually a true file object,
        # we don't need to do anything.
        if type(self.fileObj) != types.FileType:
            # The file-like object must have a read method.
            if not hasattr(fileObj, "read"):
                raise ValueError, "not a file-like object"
            
            # Create our true file object as a temp file.
            self.tmpFileObj = os.tmpfile()

            # Read from the input file-like object (via its read method)
            # in chunks so we don't chew up too much memory, and write
            # out to the temp file.
            while True:
                data = fileObj.read(self.chunksize)
                if len(data) == 0:
                    break
                self.tmpFileObj.write(data)

            del data                

            # Make sure the temp file is ready to be read from its start.
            self.tmpFileObj.flush()
            self.tmpFileObj.seek(0, 0)

            self.fileObj = self.tmpFileObj                
        return

    def file(self):
        """Return the true file object."""
        return self.fileObj

This is an application of the Adapter Pattern - "When you have an X,and you need a Y." Lesson: Your code will be more flexible if, when possible, you allow functions/methods that take a file object to also take a file-like object.