Handling 3 operands in an expression without raising an exception

Νίκος nikos.gr33k at gmail.com
Sun Sep 29 07:14:24 EDT 2013


Στις 29/9/2013 2:04 μμ, ο/η Jussi Piitulainen έγραψε:
> Steven D'Aprano writes:
>
>> On Sun, 29 Sep 2013 12:35:17 +0300, Jussi Piitulainen wrote:
>>
>>> try:
>>>    ...
>>> except socket.gaierror as e:
>>>    # watch out, a composition of bad advice (on demand) city, host = (
>>>    ('city' in locals() or "blabla"),
>>>                   ('host' in locals() or "blablabla") )
>>
>> Bad advice, and buggy as well.
>>
>> py> city = "New New York"
>> py> ('city' in locals() or "Blah blah")
>> True
>>
>> Oh man, can you imagine Nikos trying to debug that?
>
> Thanks. Sorry. This hurts. I didn't mean it to be buggy.
>
> Let's see. The task is to assign a default value to city and host, if
> they haven't a value yet; on one line (which I take to mean one
> statement); in an "except" block where we may not know which
> assignment failed in the "try" block; without "if"; but "or" is
> allowed.
>
> But the logic I was trying to implement is
>
> city, host = ( (city if 'city' in locals() else "default city"),
>                 (host if 'host' in locals() else "default host") )
>
> which uses an "if". The old tricks of using "or" and stuff for this
> would surely go too far.
>
> I know!
>
> city, host = ( locals().get('city', "default city"),
>                 locals().get('host', "default host") )

I tend to like this: I might use it because it is a clear way to tell 
what var failed in the try clause and default it to soemthing.


> Testing if the variables only exists when actually assigned:
>
>   >>> def foo(x, y):
>   ...    if x: foo = None
>   ...    if y: bar = "bar"
>   ...    return locals()
>   ...
>   >>> foo(False, False)
>   {'y': False, 'x': False}
>   >>> foo(False, True)
>   {'y': True, 'x': False, 'bar': 'bar'}
>
> Seems so.
>
> What a monster, though. I don't even want to know if this, too, is
> buggy in some way. It looks fragile.
>
> Nikos, don't do this. The way to test if an assignment failed is to
> use a try-catch. The way to know which one failed is to put each in
> its own try-catch.

Dave's way though seems better.
Assign the vars default string and if they get re-assinged correctly 
that would be ideal, otherwise we have already given them the defaults.

ipval = ( os.environ.get('HTTP_CF_CONNECTING_IP') or 
os.environ.get('REMOTE_ADDR', "Cannot Resolve") )
city = "Άγνωστη Πόλη"
host = "Άγνωστη Προέλευση"
try:
	gi = pygeoip.GeoIP('/usr/local/share/GeoIPCity.dat')
	city = gi.time_zone_by_addr( ipval )
	host = socket.gethostbyaddr( ipval ) [0]
except Exception as e:
	print( "metrites.py => (%s): " % lastvisit, repr( sys.exc_info() ), 
file=open('/tmp/err.out', 'w') )

I'll think i'll stick to this solution.




More information about the Python-list mailing list