使用 Python 进行会计的最佳实践
我正在编写一个 web2py 应用程序,需要在不损失精度的情况下对美元金额进行求和。我意识到我需要为此使用 Decimals,但我发现自己必须将从数据库中获取的每个数字包装为:
Decimal(str(myval))
在我疯狂地将其添加到之前我所有的代码,有更好的方法吗?我是 Python 新手,所以我很可能忽略了一些明显的东西。
编辑:我的数据库是 MS SQL Server,我将金额存储在 SQL Server money
字段中(我相信实现类似于 Decimal,即整数数学,而不是浮点数)观点)。
我通过 web2py 框架连接到数据库(它使用 pyodbc 进行 SQL Server 连接)。我相信 web2py 对十进制类型有一些支持。例如,我的 web2py 字段定义如下所示: Field('Amount','decimal(19,4)')
但是,当我使用 web2py 的 .executesql< 从数据库返回值时/code> 方法,它返回
float
形式的值,而不是 Decimal
。
编辑:这似乎是 FreeTDS 和 MS SQL Server 的问题。正如 Massimo 在评论中所述,web2py 正确支持这一点并返回 Decimal (如果可以的话)。事实证明这只是我的生产环境(Linux)中的一个问题。我正在使用 FreeTDS 驱动程序连接到 MS SQL,它似乎正在将 MS SQL 货币类型转换为 python 浮点数。
我认为亚历克斯·马尔泰利的答案指向了正确的方向。有人有 FreeTDS、MS SQL 和 python 的经验吗?我认为这可能有其自己的问题,所以我将转移这个讨论...(此处发布的新问题:FreeTDS 翻译 MS SQL 货币类型转换为 python float,而不是 Decimal)
更新:实际上 FreeTDS 中存在一个错误。截至 8 月 4 日,此问题已在 FreeTDS 的 CVS 头部中修复, 2010年。
I am writing a web2py application that requires summing dollar amounts without losing precision. I realize I need to use Decimals for this, but I've found myself having to wrap every single number I get from the database with:
Decimal(str(myval))
Before I go crazy adding that to all of my code, is there a better way? I'm new to Python, so it's very possible that I am overlooking something obvious.
Edit: My database is MS SQL Server and I'm storing the amounts in SQL Server money
fields (I believe the implementation is analogous to Decimal, ie integer math, not floating point).
I am connecting to the db through the web2py framework (which uses pyodbc
for SQL Server connections). I believe web2py has some support for decimal types. For example, my web2py field definitions look like: Field('Amount','decimal(19,4)')
However, when I return a value from the database using web2py's .executesql
method it returns the value as a float
and not a Decimal
.
Edit: This appears to be an issue with FreeTDS and MS SQL Server. As Massimo stated in the comments, web2py supports this properly and returns a Decimal (if it can). It turns out this is only an issue in my production environment (Linux). I am using the FreeTDS driver to connect to MS SQL and it appears to be translating the MS SQL money type to a python float.
I think Alex Martelli's answer is pointing in the right direction. Does anyone have any experience with FreeTDS, MS SQL, and python? I think this probably warrants its own question, so I'll move this discussion... (new question posted here: FreeTDS translating MS SQL money type to python float, not Decimal)
Update: There was in fact a bug in FreeTDS. This was fixed in the CVS head of FreeTDS as of August 4, 2010.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,将所有数字以十进制形式保存在数据库中 - 您没有提及您正在使用的数据库引擎,但每个引擎都支持此类功能,例如 这里是MySQL的
DECIMAL
类型文档。我希望您已经这样做了,但是,如果您没有这样做,那么架构更改的痛苦仍然值得。然后,您需要确保与数据库之间的类型转换与数据库的小数点与 Python 的小数点相匹配。不幸的是,没有跨 DB-API 实现的标准方法,但大多数都提供了一种方法;例如,使用 MySQLDB,您需要在
connect
中传递一个conv=
参数,称为“类型转换器字典”——默认值是MySQLdb 的副本.converters.conversions
但当然您可以丰富它以使用小数做正确的事情。如果您告诉我们您正在使用哪个数据库,以及您喜欢哪种 DB-API 连接器包,我们也许能够为您提供有关此主题的更详细的帮助。编辑:@unutbu 在评论中指出,当前的 MySQLdb 转换器已经可以正确转换小数,因此,除非您坚持使用非常旧的 MySQLdb 版本,否则只要您这样做就应该没问题正确地将数据库中的所有数字保留为十进制(耶!)。
First, keep all numbers in decimal form in the database -- you don't mention what DB engine you're using, but every engine supports such functionality, e.g., here is MySQL's
DECIMAL
type documentation. I hope you're already doing that, but, if you aren't, it's still worth the pain of a schema change.Then, you need to ensure the type conversion to and from the DB matches the database's decimals with Python's. Unfortunately there is no standard way to do it across DB-API implementations, but most do offer a way; for example, with MySQLDB you need to pass a
conv=
parameter inconnect
, known as a "type converters dictionary" -- the default is a copy ofMySQLdb.converters.conversions
but of course you can enrich it to do the right thing with decimals. If you tell us which DB you're using, and what DB-API connector package you prefer for it, we may be able to give you more detailed help on this subject.Edit: @unutbu remarks in a comment that the current MySQLdb converter already does translate decimals correctly, so, unless you're stuck with a very old release of MySQLdb, you should be fine as long as you do correctly keep all the numbers as decimal in the DB (yay!).
您可以编写一个函数,从数据库获取数字,然后将其转换为十进制。然后只需在您的代码中使用它即可。
You could write a function which both gets the number from the database and then converts it to decimal. Then just use that in your code.