Reputation: 2229
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!
Upvotes: 0
Views: 203
Reputation: 365915
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.
Upvotes: 2