【问题标题】:Random access csv file content随机访问csv文件内容
【发布时间】:2013-09-17 05:23:52
【问题描述】:

我正在寻找一种以随机方式访问 csv 文件单元格的方法。如果我使用 Python 的 csv 模块,我只能遍历所有相当慢的行。我还应该补充一点,该文件非常大(>100MB),而且我正在考虑缩短响应时间。

我可以将文件预处理为不同的数据格式,以便更快地访问行/列。也许有人以前做过,可以分享一些经验。

背景:

我想在 Web 服务器提供的屏幕上显示 csv 的摘录(取决于滚动位置)。不能将文件保存在内存中。

【问题讨论】:

  • 如果你不想遍历一个文件(不管是哪种格式),也许文件不是你持久化的首选。如果访问时间是一个问题,您是否考虑过使用数据库?
  • 你可以看看内存映射文件docs.python.org/2/library/mmap.html
  • 您可以遍历文件并保留单元格位置的数组,例如指向单元格的指针。然后可以使用这些来寻找特定位置。这个offcourse仍然取决于IO速度。请参阅我上面的评论,以使用大内存缓冲区来增加它。
  • 我会尝试 Joram 关于指针的回答。如果一次处理整行,则只能跟踪指向行的指针。如果它符合您的需求,您甚至可以在一些关键变量上建立索引。我已经这样做了,对大型(20 GB)文件进行统计,这样可以节省时间,但就我而言,有趣的单位是整行。
  • 你想对文件做什么?只有阅读吗?然后将从 csv 模块获得的行保存在列表中应该非常有效。如果您需要不断更新 CSV 文件并快速执行此操作,那么 SQLite 方法更适合。

标签: python csv file-io


【解决方案1】:

我发现 SQLite 非常适合这种事情。它易于设置,您可以将数据存储在本地,但与 csv 文件相比,您还可以更轻松地控制选择的内容,并且可以添加索引等。

还有一个用于将 csv 文件加载到表中的内置工具:http://www.sqlite.org/cvstrac/wiki?p=ImportingFiles

如果您想了解更多有关 SQLite 路由的详细信息,例如如何创建表、加载数据或从 Python 查询数据,请告诉我。

将 .csv 文件加载到表中的 SQLite 说明

要创建数据库文件,您只需在打开 SQLite 时添加所需的文件名作为参数。从命令行导航到包含 csv 文件的目录(我在这里假设您希望 SQLite .db 文件包含在同一目录中)。如果使用 Windows,则将 SQLite 添加到您的 PATH 环境变量中(如果需要,请使用说明 here)并按以下方式打开 SQLite,并带有您要为数据库文件提供的名称的参数,例如:

sqlite3 example.db

输入以下命令检查数据库文件是否已创建:

.databases

创建一个表来保存数据。我在这里使用一个简单的客户表的示例。如果任何列的数据类型不一致,请使用文本:

create table customers (ID integer, Title text, Forename text, Surname text, Postcode text, Addr_Line1 text, Addr_Line2 text, Town text, County text, Home_Phone text, Mobile text, Comments text);

指定要使用的分隔符:

.separator ","

发出导入数据的命令,语法格式为.import filename.ext table_name 例如:

.import cust.csv customers

检查数据是否已加载:

select count(*) from customers;

为您可能过滤的列添加索引(完整语法描述here)例如:

create index cust_surname on customers(surname);

现在,在对任何索引列进行过滤时,您应该可以快速访问数据。要离开 SQLite,请使用 .exit,要获取其他有用的非 SQL 命令列表,请使用 .help

Python 替代方案

或者,如果您想坚持使用纯 Python 并预处理文件,那么您可以将数据加载到字典中,这样可以更快地访问数据,因为字典键的行为类似于索引,这意味着您可以访问快速与键关联的值,而无需逐一查看记录。我需要您的输入数据的更多详细信息以及查找将基于哪些字段,以提供有关如何实施此操作的更多详细信息。

但是,除非您提前知道何时需要数据(以便能够在请求数据之前预处理文件),否则您仍然需要每次将文件从磁盘加载到内存中的开销你运行这个。根据您的具体使用情况,这可能会使数据库解决方案更合适。

【讨论】:

  • 我觉得数据库解决方案有点过头了,但仔细想想,它可能是一个合适的解决方案。磁盘开销是多少,您会选择哪种表结构。有没有一种简单的方法可以从 Python 加载文件?字典不起作用,因为我无法将整个文件加载到内存中。
  • 如果你的意思是 SQLite 程序在磁盘上占用了多少空间,那它是非常小的。可执行文件约为 0.5 MB 并且,(源代码约为 5 MB,但您不需要保留它)。就数据结构而言,我需要更多地了解您的数据才能提供建议。您可以在问题中发布一些示例行吗?
  • Sqlite 已经是 Python 标准库(恕我直言)的一部分。我想问的是 sqlite 数据库文件的大小与 csv 文件的比较。至于 csv 记录,列是未标记的(未定义它们具有什么类型或含义)。您会将它们与行/列主键和字符串值一起存储吗?
  • @orange 我已经用一些说明和将 .csv 文件导入 SQLite 的示例更新了上面的答案。让我知道这是否需要进一步解释。为了回答您关于文件开销的问题,SQLite 创建的 .db 文件比我的示例中的 csv 文件(15MB csv 文件)占用了大约 10% 的空间,这可能会因数据而异,但开销不应该是太重要了。
  • 我可能最终会在 Python 中进行导入并将其写入 sqlite 数据库。将所有这些数据保存在 dict 中对我来说不是一个可行的选择,因为它可能非常大。
猜你喜欢
  • 2011-06-16
  • 1970-01-01
  • 1970-01-01
  • 2015-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-22
  • 1970-01-01
相关资源
最近更新 更多