【问题标题】:Unable to store huge strings in-memory无法在内存中存储巨大的字符串
【发布时间】:2014-11-18 06:06:40
【问题描述】:

我有以下形式的数据:

#@ De
A B C.
#@ dabc
xyz def ghi.
#@ <MyName_1>
Here is example.
#@ Df
A B C.
#@ <MyName_2>
De another one.
#@ <MyName_3>
Df next one.
#@ dabc1
xyz def ghi.
#@ <MyName_4>
dabc this one.

转换成如下形式:

A B#1 C. //step 1 -- 1 assigned to the first occurrence of A B C.
xyz def#1 ghi. //1 assigned to first occurrence of xyz def ghi
Here is example
A B#2 C. //step 1 -- 2 assigned in increasing order
B#1 another one. //step 2
B#2 next one.
xyz def ghi.
def#1 this one.

// 这里代表 cmets,不是输出的一部分。

算法如下。

  1. 如果#@ 之后的第二行重复。然后,附加到 中间字#number,其中 number 是数字标识符,并且是 按第二行的重复顺序递增。
  2. 将 #@... 替换为 word#number 出现的位置。
  3. 删除第二行没有重复的所有#@。

为了实现这一点,我存储了所有三元组,然后找到它们的出现,以便按递增顺序分配数字。有没有其他方法可以在 python 中实现相同的功能。实际上我的文件是 500GB,不可能将所有三元组都存储在内存中以查找它们的出现。

【问题讨论】:

  • @JoranBeasley 好的。您能否说明如何使用数据库来做同样的事情......因为我是在 python 中使用数据库的新手
  • 第二行如何从A B C. 转换为A B#1 C.? (我猜// cmets 不是输出的一部分?)我没有看到应该使这种情况发生的三个规则中的任何一个。
  • @abamert 是的,你是对的 // 是 cmets。我使用它们是为了说明这一点。
  • 如果一切都失败了,使用 64 位版本的 Python 应该可以解决问题。
  • 同时,您的文件为 500GB 的事实并不一定意味着这会占用太多内存;这取决于你有多少不同的三元组。那是多少?你确定你没有以其他方式浪费内存(例如,通过readlines()-在处理之前将整个文件放入内存,或者通过构建一个巨大的列表而不是一次写入一行等)?

标签: python regex linux python-2.7


【解决方案1】:

如果您需要类似于 dict 但太大而无法在内存中保存的东西,那么您需要的是键值数据库。

最简单的方法是使用dbm-type 库,这是一个非常简单的键值数据库,其接口与dict 几乎完全相同,只是它只允许键和值的字符串,并且有一些额外的方法来控制持久性和缓存等。根据您的平台和 Python 2.7 的构建方式,您可能有以下任何一种:

如果您的 Python 安装不包含最后三个,则它们都可以在 PyPI 上使用,只要您拥有相关版本的 libbsddb 本身并且其许可证没有任何问题。

问题在于,根据您的平台,各种底层数据库可能不存在(当然您可以下载 C 库,安装它,然后构建并安装 Python 包装器),或者可能不支持数据库大,或者可能会这样做,但只是以一种非常低效的方式(或者,在少数情况下,以一种错误的方式......)。

希望其中一个对你有用,但你真正知道的唯一方法是测试你所有的。

当然,如果我理解正确,您将字符串映射到整数,而不是字符串。您可以使用 shelve 模块,它包装了任何类似 dbm 的库,以允许您使用字符串键,但可以使用任何可挑选的值……但对于这样的情况,这太过分了(并且可能会影响您的性能);你只需要像这样更改代码:

counts.setdefault(key, 0)
counts[key] += 1

……进入这个:

counts.setdefault(key, '0')
counts[key] = str(int(counts[key]) + 1)

当然,您可以轻松编写一个为您执行此操作的包装类(甚至可能支持Counter 接口而不是dict 接口)。


如果这不起作用,您需要更强大的数据库。

大多数 Python 版本都在 stdlib 中附带 sqlite3,但使用它需要学习相当低级的 API 和 SQL,这是一种完全不同的语言,与 Python 非常不同。 (也有各种不同的关系数据库,但您不应该需要它们。)

还有各种查询表达式库,甚至是完整的对象关系映射器,例如 SQLAlchemy(可以使用任何一种方式),它们可以让您以更加 Python 的方式编写查询,但它仍然不会就像使用dictdbm 一样简单。 (话虽如此,在SQLAlchemy 周围包裹一个类似dbm 的界面并不难。)

还有各种各样的非关系型或半关系型数据库,它们通常被归为NoSQL 一词,其中最简单的基本上是类固醇上的dbm。同样,他们通常需要学习一个非常低级的 API,有时还需要学习一种查询语言——但其中一些会有很好的 Python 库,使它们更易于使用。

猜你喜欢
  • 2015-06-11
  • 1970-01-01
  • 1970-01-01
  • 2014-04-18
  • 2011-01-13
  • 2012-09-06
  • 2014-12-25
  • 2016-02-23
  • 1970-01-01
相关资源
最近更新 更多