2010-02-19 160 views
3

我正在用Python讀取600萬條.csv文件,並且我希望能夠通過此文件搜索特定條目。如何通過Python中的.csv文件快速搜索

是否有任何技巧來搜索整個文件?你應該把整個東西都讀成字典嗎?還是每次都要進行搜索?我試着將它加載到字典中,但這花了很長時間,所以我每次都在搜索整個文件,這看起來很浪費。

我可以利用列表按字母順序排列嗎? (例如,如果搜索詞以「b」開頭,則僅從包含以「b」開始的第一個詞的行到包括以「b」開頭的最後一個詞的行)搜索

我正在使用import csv

(側面的問題:它有可能使csv去一個特定的行文件中我想使程序開始在隨機線)

編輯:我已經有了的副本列表作爲一個.sql文件,我怎麼能實現它到Python?

+5

我會先將文件導入數據庫。 – Seth 2010-02-19 21:06:07

+0

我忘了提及我不是一個Python專家,所以我們將不勝感激代碼示例。 – 2010-02-19 21:12:02

+0

每次運行腳本時,您會執行多少次查找? – 2010-02-19 23:23:22

回答

6

如果csv文件沒有更改,請將其加載到數據庫中,在該數據庫中搜索快速且容易。如果你不熟悉SQL,那麼你需要重新學習一下。

下面是從csv插入到sqlite表的粗略示例。示例csv是';'分隔,並有2列。

import csv 
import sqlite3 

con = sqlite3.Connection('newdb.sqlite') 
cur = con.cursor() 
cur.execute('CREATE TABLE "stuff" ("one" varchar(12), "two" varchar(12));') 

f = open('stuff.csv') 
csv_reader = csv.reader(f, delimiter=';') 

cur.executemany('INSERT INTO stuff VALUES (?, ?)', csv_reader) 
cur.close() 
con.commit() 
con.close() 
f.close() 
+0

我曾經希望我不用SQL來做到這一點,Python應該幾乎和Perl處理字符串一樣快? SQL真的更快嗎? ()我想使用Linux,所以請嘗試建議使用跨平臺軟件 – 2010-02-19 21:51:17

+0

com.close()應該是con.close() – pwdyson 2010-02-19 21:51:39

+2

@Baldur - 這不是perl vs python的問題,你的問題是你正在反覆閱讀一個大文件。 Perl和python會以同樣的方式做到這一點。數據庫只是爲您提供更好的索引和搜索界面。 – JimB 2010-02-19 21:59:01

1

好了,如果你的話是不是太大(這意味着他們將存放在內存),那麼這裏有一個簡單的方法來做到這一點(我假設他們都是的話)。

from bisect import bisect_left 

f = open('myfile.csv') 

words = [] 
for line in f: 
    words.extend(line.strip().split(',')) 

wordtofind = 'bacon' 
ind = bisect_left(words,wordtofind) 
if words[ind] == wordtofind: 
    print '%s was found!' % wordtofind 

加載文件中的所有值可能需要一分鐘。這使用二進制搜索來找到你的話。在這種情況下,我正在尋找培根(誰不會尋找培根?)。如果存在重複的值,您可能還想使用bisect_right查找等於您要搜索的值的最右側元素之外的索引1。如果您有鍵:值對,您仍然可以使用它。你只需要讓你的單詞列表中的每個對象都是[鍵,值]的列表。

旁註

我不認爲你可以真正從線走在CSV文件中排隊很容易。你看,這些文件基本上只是長字符串,用\ n字符表示新行。

4

你可以使用內存映射非常大的文件

import mmap,os,re 
reportFile = open("big_file") 
length = os.fstat(reportFile.fileno()).st_size 
try: 
    mapping = mmap.mmap(reportFile.fileno(), length, mmap.MAP_PRIVATE, mmap.PROT_READ) 
except AttributeError: 
    mapping = mmap.mmap(reportFile.fileno(), 0, None, mmap.ACCESS_READ) 
data = mapping.read(length) 
pat =re.compile("b.+",re.M|re.DOTALL) # compile your pattern here. 
print pat.findall(data) 
1

您不能直接轉到特定行的文件,因爲行是可變長度,所以唯一的辦法知道線#N時首先是搜索前n個換行符。它是不夠的,只認準「\ n」字符,因爲CSV允許換行表格單元格,所以你真的有反正來解析文件。

0

我的想法是使用Python ZODB模塊存儲dictionaty類型的數據,然後使用該數據結構創建新的CSV文件。當時做你所有的手術。

0

有一個相當簡單的方式來做到這一點。根據你想要打印多少列,你可能需要添加或刪除一些打印行。

import csv 
search=input('Enter string to search: ') 
stock=open ('FileName.csv', 'wb') 
reader=csv.reader(FileName) 
for row in reader: 
    for field in row: 
     if field==code: 
      print('Record found! \n') 
      print(row[0]) 
      print(row[1]) 
      print(row[2]) 

我希望這個設法幫助。