Join the Stack Overflow Community
Stack Overflow is a community of 6.3 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I'm trying to find out why I'm seeing this. This is the code-snippet:

def check_status(addr,port=80):

    import urllib2

    if not addr.startswith('http://'): addr = "http://" + addr
    req = urllib2.Request(addr+":"+str(port))

    try:
        res = urllib2.urlopen(req,None,10)
        sts = str(res.code)

    except urllib2.URLError, er:
        sts = er.args

    print "Print-1\t: %s" % sts
    print "Print-2\t:", sts
    print "{0}\t: {1}".format('Print-3',sts)
    return sts


url = "google.comm"
sts = check_status(url)
print "Print-4\t: %s  %s" % (url, sts)

Running the script, I get interesting result on print statement:

Print-1 : [Errno 8] nodename nor servname provided, or not known
Print-2 : (gaierror(8, 'nodename nor servname provided, or not known'),)
Print-3 : (gaierror(8, 'nodename nor servname provided, or not known'),)
Print-4 : google.comm  (gaierror(8, 'nodename nor servname provided, or not known'),)

Can anyone please explain why printing sts coming differently for print-2, 3 and 4? It's printing in correct format only with single %s formatting-string. I don't think it's got anything to do with urllib2. What am I missing here? Thanks!

share|improve this question
1  
Out of curiosity, why are you doing sts = str(res.code) in the success case, but not sts = str(er.args) in the error case? (If you'd done that, this issue would never have come up, and you wouldn't have learned something new, so it's probably for the best. It's just that I'm having a hard time understanding why an integer isn't an acceptable value to pass around, but a tuple of arbitrary exception arguments is.) – abarnert May 30 '13 at 19:12
    
@abarnert: That's an interesting question really. I guess I did that to make sure I'm retuning a string, not a integer. It's actually a very old script of mine, which I was working on to add some extra stuff and got hit by the result. BTW, str(er.args) doesn't change any thing for me at all. Cheers!! – MacUsers May 30 '13 at 19:34
up vote 2 down vote accepted

Passing a single argument to % is ambiguous, so Python applies a rule that's confusing in some cases, but most often the answer you wanted. If the argument is not a tuple, it's treated as if it were wrapped in a 1-element tuple.

So this:

print "Print-1\t: %s" % sts

… prints str(sts[0]) if it's a 1-element tuple, and raises a TypeError if it's a tuple of any other length, but prints str(sts) if it's just a string (or an Exception or whatever).

All of your other examples:

print "Print-2\t:", sts
print "{0}\t: {1}".format('Print-3',sts)
print "Print-4\t: %s  %s" % (url, sts)

… just print str(sts), because they don't have this magic rule.

In your case, sts is a 1-element tuple. So, str(sts[0]) is what you want, because str(sts) is equivalent to '(' + repr(sts[0]) + ',)'. You got lucky with Print-1 because you hit the magic rule by accident. (You may not even have known that er.args was a tuple.)


This kind of confusion is exactly why people keep suggesting deprecating %-formatting, or changing it so it always treats its argument as a sequence, etc. But because it's so handy for so many quick&dirty purposes, those suggestions always get defeated.

One way to avoid confusing yourself is to always pass even a single argument as a tuple: print "Print-0\t: %s" % (sts,). Or just don't use %-formatting.

share|improve this answer
    
.args is a tuple. – Martijn Pieters May 30 '13 at 18:59
    
@MartijnPieters: Yes, that's why Print-1 treats it differently from the others: because, unlike the others, it prints str(sts[0]) if its a tuple (which it is). But I edited the answer to make that clearer. – abarnert May 30 '13 at 19:04
    
Yup, just confirming that .args is a tuple. – Martijn Pieters May 30 '13 at 19:07
    
Thanks abarnert for explaining. I see a simply supplying a position, like this: print "Print-2\t:", sts[0] just fixes everything. And thanks to Martijn to pointing out that's actually a tuple(). – MacUsers May 30 '13 at 19:31

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.