随机访问CSV文件内容

3
我正在寻找一种随机访问csv文件单元格的方法。如果我使用Python的csv模块,我只能迭代所有行,这相当慢。值得一提的是,文件非常大(>100MB),而且我希望响应时间短。
我可以预处理文件以获得更快的行/列访问速度。也许有人之前已经做过这个,并且可以分享一些经验。
背景:
我想在网页上显示由Web服务器提供的csv摘录(取决于滚动位置)。将文件保存在内存中不是一个选项。

6
如果您不想遍历文件(无论其格式是什么),或许文件并不是您首选的持久化方式。如果访问时间是一个问题,您考虑过使用数据库吗? - Hyperboreus
2
你可以查看内存映射文件的相关内容,链接为http://docs.python.org/2/library/mmap.html。 - Joram
1
你可以迭代文件并保持一个单元格位置的数组,就像指向单元格的指针一样。然后可以使用它们来寻找特定位置。当然,这仍然取决于IO速度。查看我上面的评论以了解如何通过大内存缓冲区增加速度。 - Joram
我会尝试Joram关于指针的答案。如果您一次处理整行,则只需跟踪对行的指针即可。如果符合您的需求,则甚至可以在某些关键变量上构建索引。我已经这样做了,可以对大型(20 GB)文件进行统计,这可以节省时间,但在我的情况下,有趣的单位是整行。 - user1220978
你想对这个文件做什么?只是读取它吗?那么,将从csv模块获取的行保存在列表中应该非常高效。如果您需要不断更新CSV文件并快速执行此操作,则SQLite方法更适合。 - Eric O. Lebigot
显示剩余10条评论
1个回答

4
我发现SQLite非常适合这种情况。它易于设置,可以将数据存储在本地,但是相比于csv文件,您可以更轻松地控制所选内容,并且还可以添加索引等功能。
还有一种内置的方法可以将csv文件加载到表中:http://www.sqlite.org/cvstrac/wiki?p=ImportingFiles
如果您需要SQLite路线的更多详细信息,例如如何创建表格、加载数据或从Python查询数据,请告诉我。
将.csv文件加载到表中的SQLite说明:
要创建一个数据库文件,您只需在打开SQLite时将所需的文件名作为参数添加即可。从命令行导航到包含csv文件的目录(在此假设您希望SQLite .db文件包含在同一目录中)。如果使用Windows,则如果尚未完成,请将SQLite添加到PATH环境变量中(如果需要说明,请单击此处),然后使用以下方式打开SQLite并指定您要为数据库文件命名的名称的参数:
sqlite3 example.db

检查数据库文件是否已创建,请输入以下内容:

.databases

创建一个表来存储数据。我这里以一个简单的客户表作为例子。如果某些列的数据类型不一致,请使用text类型:
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;

为那些你可能会进行过滤的列添加索引(完整语法描述在这里),例如:

create index cust_surname on customers(surname);

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

Python替代方案

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

但是,除非您事先知道何时需要数据(以便能够在请求数据之前预处理文件),否则每次运行此操作时仍会将文件从磁盘加载到内存中,这样会有负担。根据您的确切用法,这可能使数据库解决方案更合适。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接