如何防止csv.DictWriter()或writerow()舍入我的花车?

aDr*_*oid 11 python csv floating-point file-io rounding

我有一个字典,我想写一个csv文件,但是当我把它们写入文件时,字典中的浮点数会四舍五入.我想保持最高精度.

四舍五入发生在哪里,我该如何防止它?

我做了什么

我在这里遵循了DictWriter示例,我在Mac上运行Python 2.6.1(10.6 - Snow Leopard).


# my import statements
import sys
import csv
Run Code Online (Sandbox Code Playgroud)

这是我的字典(d)包含的内容:

>>> d = runtime.__dict__
>>> d
{'time_final': 1323494016.8556759,
'time_init': 1323493818.0042379,
'time_lapsed': 198.85143804550171}
Run Code Online (Sandbox Code Playgroud)

这些值确实是浮点数:

>>> type(runtime.time_init)
<type 'float'>
Run Code Online (Sandbox Code Playgroud)

然后我设置我的编写器并编写标题和值:

f = open(log_filename,'w')
fieldnames = ('time_init', 'time_final', 'time_lapsed')
myWriter = csv.DictWriter(f, fieldnames=fieldnames)
headers = dict( (n,n) for n in fieldnames )
myWriter.writerow(headers)
myWriter.writerow(d)
f.close()
Run Code Online (Sandbox Code Playgroud)

但是当我查看输出文件时,我得到了舍入的数字(即浮点数):

time_init,time_final,time_lapsed
1323493818.0,1323494016.86,198.851438046
Run Code Online (Sandbox Code Playgroud)

<EOF>

Ray*_*ger 6

看起来csv使用float .__ str__而不是float .__ repr__:

>>> print repr(1323494016.855676)
1323494016.855676
>>> print str(1323494016.855676)
1323494016.86
Run Code Online (Sandbox Code Playgroud)

查看csv源代码,这似乎是一种硬连线行为.解决方法是在csv到达之前将所有浮点值强制转换为其repr.使用类似的东西:d = dict((k, repr(v)) for k, v in d.items()).

这是一个经过实践证明的例子:

import sys, csv

d = {'time_final': 1323494016.8556759,
     'time_init': 1323493818.0042379,
     'time_lapsed': 198.85143804550171
}

d = dict((k, repr(v)) for k, v in d.items())

fieldnames = ('time_init', 'time_final', 'time_lapsed')
myWriter = csv.DictWriter(sys.stdout, fieldnames=fieldnames)
headers = dict( (n,n) for n in fieldnames )
myWriter.writerow(headers)
myWriter.writerow(d)
Run Code Online (Sandbox Code Playgroud)

此代码生成以下输出:

time_init,time_final,time_lapsed
1323493818.0042379,1323494016.8556759,198.85143804550171
Run Code Online (Sandbox Code Playgroud)

更精细的方法将只关注浮动的替换:

d = dict((k, (repr(v) if isinstance(v, float) else str(v))) for k, v in d.items())
Run Code Online (Sandbox Code Playgroud)

注意,我刚刚修复了Py2.7.3的这个问题,所以它不应该成为一个问题.见 http://hg.python.org/cpython/rev/bf7329190ca6

  • 真棒.我不知道这里有多少问题直接对来源做出贡献,但对于我的第一个问题,我很高兴我发布了它!过去几周我一直在使用Python,而且我已经在使用它了,现在我的更改(即你代表我所做的更改)已经合并到源代码中,我现在可以说我已经完全被同化了通过Python.:) 再次感谢. (2认同)