[spambayes-dev] RE: [Python-Dev] RE: [Spambayes] Question (orpossibly a bug report)

Tim Peters tim.one@comcast.net
Fri, 25 Jul 2003 00:57:21 -0400


[Tony Meyer]
> ...
> Is it possible that Outlook simply changes the crt locale at some
> point completely unrelated to spambayes activity?

Oh yes!  Outlook is usually running 16 (or more) threads, and one of the
joys of locale is that it's global (shared) state.  Any thread can change it
at any time, and the change is seen by all threads.

> This would explain why I can't narrow down a call that does it.  If
> that's the case, then the only solution is a band-aid one, isn't it -
> where we fix the locale each time, before we do anything with floats.

It really doesn't matter when we *use* floats.  What matters is the locale
setting at the time Python's (un)marshal code calls C's atof() when it's
building code objects from a .pyc file.  Building a code object is a
once-per-life-of-the-program-run thing, and happens at import time.  Once
the code object is constructed, the locale setting becomes irrelevant.

Really understanding this requires learning more about Python internals than
anyone (other than a Python implementer) should ever need to know.  Here's a
clue:

>>> def f():
...     return 1.23 + 4.56
...
>>> f.func_code.co_consts
(None, 1.23, 4.5599999999999996)
>>>

A code object's co_consts attribute is a tuple of all objects that
correspond to literals in the source code (the None there is from the
implicit "return None" at the end of every function).  Part of what
unmarshal does is to convert a string of bytes in the .pyc file into a code
object's co_consts tuple.  That's an immutable thing (like all tuples are),
and holds actual Python float (and string, etc) objects.  Once those are
created, changes to locale can't hurt them -- it's already a done deal.

> (And avoid floats by using float(1)/10 and so forth).

That rule is really painful to live with.  Unfortunately, AFAIK, some thread
in Outlook *could* change locale while the thread loading a Python .pyc file
is in the middle of doing its stuff.

Heh.  We could start our modules with something like

    if 1.23 != float(123)/100:
        do sick magic to force a reload of the module

Mark should love that one <wink>.