just another default argument value gotcha

Frank Bechmann fBechmann at web.de
Mon Dec 29 04:33:59 EST 2003


Eventually most of you will not learn much from this because it's just
another event in the 'default argument value gotcha' series, but
because it cost me some hours yesterday to spot this 'error' in a
famous python tool I thought it might still help other people to save
some time.

I tried to use some method which was documented to write to
'sys.stdout' per default so that changing 'sys.stdout' to bind to
another object should allow to get grip on the method's output. but
that didn't work - reason was that that 'sys.stdout' was used as
default argument value for the method. The following code describes it
better then my english can do, so as it seems for me, one should make
sure to use the 'f2' variant.

import StringIO, sys

def f1(msg, out=sys.stdout):
    out.write("%s\n" % msg)

def f2(msg, out=None):
    if not out: 
        out = sys.stdout
    out.write("%s\n" % msg)

if __name__ == "__main__":
    buf = sys.stdout = StringIO.StringIO()
    f1("calling f1")
    f2("calling f2")
    data = buf.getvalue()
    buf.close()
    sys.stdout = sys.__stdout__
    print "=========\n", data

results in:

    calling f1                 <-- written directly by 'f1'
    ==========                     => redirection didn't work 
    calling f2                 <-- written from data stored in 'buf'


running the following greps on this machine brought only 2 possible
spots, but that doesn't mean too much since this is our gaming
computer with only a very basic python installation; eventually
someone with a real huge package list would bring up more hits:

$ find . -name '*.py' -exec grep -H '\bdef\b.*\(.*\=sys.stdout.*\)[
\t]*:' \{} \;
>> ./test/test_grammar.py:def tellme(file=sys.stdout):
$ find . -name '*.py' -exec grep -H '\bdef\b.*\(.*\=sys.stderr.*\)[
\t]*:' \{} \;
>> ./unittest.py:    def __init__(self, stream=sys.stderr,
descriptions=1, verbosity=1):




More information about the Python-list mailing list