【问题标题】:Efficient data interchange format using only C-style fprintf() statements?仅使用 C 风格的 fprintf() 语句的高效数据交换格式?
【发布时间】:2012-12-21 21:23:54
【问题描述】:

我需要将非常大的数据集(1-10 百万条记录之间,可能更多)从特定领域的语言(其唯一的输出机制是 C 风格的 fprintf 语句)传输到 Python。

目前,我正在使用 DSL 的 fprintf 将记录写入平面文件。平面文件如下所示:

x['a',1,2]=1.23456789012345e-01
x['a',1,3]=1.23456789012345e-01
x['a',1,4]=1.23456789012345e-01
y1=1.23456789012345e-01
y2=1.23456789012345e-01
z['a',1,2]=1.23456789012345e-01
z['a',1,3]=1.23456789012345e-01
z['a',1,4]=1.23456789012345e-01

如您所见,每条记录的结构非常简单(但将双精度浮点数表示为 20 字符的字符串效率非常低!):

<variable-length string> + "=" + <double-precision float>

我目前正在使用 Python 读取每一行并将其拆分为“=”。

我可以做些什么来使表示更紧凑,以便让 Python 更快地阅读? fprintf 是否可以进行某种二进制编码?

【问题讨论】:

    标签: python binaryfiles printf dataformat data-representation


    【解决方案1】:

    错误.... 你每分钟从 Python 读取这些数据多少次?

    因为在我的系统中,我可以在一秒钟内读取这样一个包含 2000 万条记录 (~400MB) 的文件。

    除非您在有限的硬件中执行此操作,否则我会说您太担心什么了。

    >>> timeit("all(b.read(20) for x in xrange(0, 20000000,20)  ) ", "b=open('data.dat')", number=1)
    0.2856929302215576
    >>> c = open("data.dat").read()
    >>> len(c)
    380000172
    

    【讨论】:

    • 感谢您的回答。我用 2000 万条随机生成的记录分析了我的代码。花了4.8秒读完,还是可以接受的。我猜真正的瓶颈是每条记录上的字符串拆分操作(我认为这会受益于通过编码获得的较短字符串),但是在将其从 line.split("=") 更改为 line.split("=", 1) 之后,我得到了合理的加速。所以看来我毕竟真的不需要编码。
    【解决方案2】:

    basic encoding rules (BER) 中定义了用于序列化浮点值的紧凑二进制格式。在那里,它们被称为“真实”。有可用的 Python BER 实现,但也不太难编写。也有 C 的库。您可以使用这种格式(这就是它的设计目的)或变体(CER、DER)。一种这样的 Python 实现是pyasn1

    【讨论】:

    • 原来瓶颈不是 Python 的读取操作。但是,我以前从未听说过 BER,这听起来像是我将来可能会使用的东西。您的回答还给了我关于 wiki 内容的提示(“数据序列化”、“asn.1”等)。现在我知道下次需要序列化格式时要查找什么。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-12
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多