私はこの男と同じ問題を抱えており、おそらくこの男と同じ問題を抱えていますが、コードを共有して質問に答えるために周りにいます!
pyodbc を介して Microsoft Access データベースからフィールドを読み取り、表示用に出力を準備するバッチ ジョブのコードがいくつかあります。
ここにスニペットがあります。アサートに注意してください。
def format_currency(amount):
if amount is None:
return ""
else:
result = "$%.2f" % amount
assert ":" not in result, (
"That's weird. The value %r of class %s is represented as %s" %
(amount, amount.__class__, result))
return result
実行すると、100,000 行を正常に処理してから失敗します。
AssertionError: That's weird. The value Decimal('54871.0000') of class <class
'decimal.Decimal'> is represented as $54870.:0
異常な結腸に注意してください。めったに発生しません - 300,000 レコードに約 1 回です。
もちろん、それを分離しようとすると、うまくいきます。
from decimal import Decimal
print "$%.2f" % Decimal('54871.0000')
$54871.00
Access のフィールドの型は次のとおりです。
- データ型: 通貨
- 小数点以下の桁数: 2
- 入力マスク:
- デフォルト値:
- 検証規則:
- テキストの配置: 一般
不十分な証拠に基づく私の漠然とした指差しの疑い: pyodbc は、おそらく Access の破損によって混乱している、Decimal の内部を突っついています。@ecatmur が指摘するように:
':' は ASCII の '9' + 1 です
これを見て解決した人いますか?
バージョン:
- パイソン 2.7.4
- pyodbc 3.0.6 (最新)
- アクセス 2010
- ウィンドウズ7
さらに掘り下げる:
decimal
モジュールは Python で実装されています。_exp
私の読書によると、値は、_int
、_sign
、の 4 つの属性で表されます。_is_special
破損を疑って、これらのフィールドの値を出力しました。
驚いたことに、障害のあるバージョンと動作中のバージョンの両方で、次のようになります。
_exp: -4
_int: 548710000
_sign: 0
_is_special: False
それは変だ。
decimal
モジュールでは、__float__
関数はかなり単純に定義されています。
def __float__(self):
"""Float representation."""
return float(str(self))
しかし、悪いデータでこれを行うと:
print "Str", str(amount)
print "Float", float(amount)
私は得る:
筋力 54871.0000
フロート 54870.:
学べば学ぶほど、奇妙に感じなくなります。