[Peter Hansen] >> I'm investigating a puzzling problem involving an attempt to >> generate a constant containing an (IEEE 754) "infinity" value. (I >> understand that special float values are a "platform-dependent >> accident" etc...)
[also Peter] > ... > My guess about marshal was correct. Yup. > The problem (value becoming 1.0) appears when running from .pyc > files. Immediately after the source code is changed, the code works, > since it doesn't unmarshal the .pyc file but just works from the > bytecode freshly compiled in memory. > > This demonstrates what would be the heart of the problem, which I guess > means this is not surprising to almost anyone, but perhaps will be a > wakeup call to anyone who might still be unaware and has code that > relies on constants like 1e6666 producing infinities: It has a much better chance of working from .pyc in Python 2.5. Michael Hudson put considerable effort into figuring out whether the platform uses a recognizable IEEE double storage format, and, if so, marshal and pickle take different paths that preserve infinities, NaNs, and signed zeroes. For Pythons earlier than that, it's a better idea to avoid trying to express special values as literals. That not only relies on platform accidents about how marshal works, but also on platform accidents about the C string->float library works. For example, do instead: inf = 1e300 * 1e300 nan = inf - inf If you're /on/ an IEEE-754 platform, those will produce an infinity and a NaN, from source or fom .pyc. > >>> import marshal > >>> marshal.dumps(1e666) > 'f\x061.#INF' > >>> marshal.loads(marshal.dumps(1e666)) > 1.0 Illustrating the remarkable truth that the Microsoft C float->string routines can't read what the MS string->float routines produce for special values (try reading "1.#INF" from C code with a double format and you'll also get 1.0 back). Here in Python 2.5, on Windows (note that marshal grew a new binary float format, primarily to support this): >>> import marshal >>> marshal.dumps(1e666) 'g\x00\x00\x00\x00\x00\x00\xf0\x7f' >>> marshal.loads(_) 1.#INF >>> float.__getformat__('double') # also new in 2.5 'IEEE, little-endian' -- http://mail.python.org/mailman/listinfo/python-list