[Tutor] Proxies/Interceptors for file-like objects

Oxymoron moron.oxy at gmail.com
Thu Feb 19 10:12:57 CET 2009


Thanks for the answers everyone.

Denis, I wish to wrap an already open file handle basically, so simply
extending and overriding doesn't help - my proxy won't be instantiated
like a file, just used like one and if not intercepting I need to
delegate down to the proxied "real" handle. If I'm missing something,
please let me know. Here's the actual scenario:

1. The script is called within a CGI environment, so I get sys.stdin
which I wish to wrap
2. On calls to read, I wish to perform certain actions (I am not the
one doing the reading - I pass my proxy to the reader process - very
trojan horse like), but the read is still done by the sys.stdin
object.

So far I've gone with Kent's suggestion, I have been a bit lazy and
did not look up new-style classes, got it working with the old-style
get attr, like so:

class FileProxy:
    def __init__(self, wrappedfp, readhook):
        """wrappedfp is the fp we delegate down to, readhook is a
callable(proxy) which is called
        on read operations"""
        self.fp = wrappedfp
        self.readhook = readhook
        self.bytecount = 0

    def __getattr__(self, attrib):
        return getattr(self.fp, attrib)

    def read(self, size=-1):
        d = self.fp.read(size)
        self.readhook(self)
        return d

    def readline(self, size=-1):
        d = self.fp.readline(size)
        self.readhook(self)
        return d

It seems to do what I want. I suppose extending from the actual type
is 'safer' in that code that relies on it being a subtype won't
break... hmm, fairly narrow scenario I have here though :-).

Thanks.

-- Kamal

On Thu, Feb 19, 2009 at 7:56 PM, spir <denis.spir at free.fr> wrote:
>
> But... why not use the proper type instead:
>
> class F(file):
>        def __init__(self, file_name):
>                self.file_name = file_name
> f = F("/home/prog/io/test.py")
> print dir(f)
> print isinstance(f,types.FileType)
> ==>
> ['__class__', '__delattr__', '__dict__', '__doc__', '__enter__', '__exit__', '__getattribute__', '__hash__', '__init__', '__iter__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'close', 'closed', 'encoding', 'file_name', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines']
> True
>
> Then, overload the proper method the call of which you need to catch. Or there is a "detail" I do not "catch" ;-)
>
> Denis
> ------
> la vita e estrany
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
>


More information about the Tutor mailing list