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.
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.