2014-10-16 18 views
13

Vấn đề mà tôi đang gặp phải là tôi có một tập tin rất lớn (2.6 Gb) mà tôi đang cố gắng mở nhưng mỗi khi tôi làm như vậy, tôi nhận được một lỗi bộ nhớ. Tôi nhận ra bây giờ rằng tôi nên đã sử dụng một cơ sở dữ liệu để lưu trữ tất cả các thông tin nhưng quá muộn của nó bây giờ. Tệp dưa chuột chứa ngày và văn bản từ hồ sơ Quốc hội Hoa Kỳ đã được thu thập dữ liệu từ internet (mất khoảng 2 tuần để chạy). Có cách nào tôi có thể truy cập thông tin mà tôi đã chuyển vào tệp dưa tăng dần hay cách chuyển đổi tệp dưa vào cơ sở dữ liệu sql hoặc một thứ khác mà tôi có thể mở mà không phải nhập lại tất cả dữ liệu. Tôi thực sự không muốn phải mất thêm 2 tuần nữa để thu thập lại hồ sơ quốc hội và đưa dữ liệu vào cơ sở dữ liệu.Tập tin Pickle quá lớn để tải

Cảm ơn bó giúp đỡ của bạn

EDIT *

mã cho cách đối tượng được ngâm:

def save_objects(objects): 
    with open('objects.pkl', 'wb') as output: 
     pickle.dump(objects, output, pickle.HIGHEST_PROTOCOL) 

def Main(): 
    Links() 
    file = open("datafile.txt", "w") 
    objects=[] 
    with open('links2.txt', 'rb') as infile: 
     for link in infile: 
      print link 
      title,text,date=Get_full_text(link) 
      article=Doccument(title,date,text) 
      if text != None: 
       write_to_text(date,text) 
       objects.append(article) 
       save_objects(objects) 

Đây là chương trình với các lỗi:

def Main(): 
    file= open('objects1.pkl', 'rb') 
    object = pickle.load(file) 
+0

Máy chạy chương trình có RAM bao nhiêu RAM? – IanAuld

+0

Sử dụng sqlite, để chọn một tệp 2.6 Gb là khá gần với sự điên rồ. Sqlite là khá dễ dàng để có được xung quanh;) – brunsgaard

+0

Chia sẻ dữ liệu và tôi sẽ giải thích nó cho bạn hoặc thuê một máy AWS lớn cho công việc. Tôi khá chắc chắn @IanAuld là đúng .. bạn thiếu bộ nhớ. – brunsgaard

Trả lời

8

Bạn đã không chọn dữ liệu của bạn tăng dần. Bạn đã chọn dữ liệu của bạn nguyên khối và lặp đi lặp lại. Mỗi lần xung quanh vòng lặp, bạn đã hủy bất kỳ dữ liệu đầu ra nào bạn đã có (open(...,'wb') phá hủy tệp đầu ra) và viết lại tất cả dữ liệu một lần nữa. Ngoài ra, nếu chương trình của bạn đã từng dừng và sau đó khởi động lại với dữ liệu đầu vào mới, dữ liệu đầu ra cũ sẽ bị mất.

Tôi không biết tại sao objects không gây ra lỗi ngoài bộ nhớ trong khi bạn đang ngâm, vì nó đã tăng lên cùng kích thước với đối tượng mà pickle.load() muốn tạo.

Đây là cách bạn có thể tạo ra các tập tin dưa từng bước:

def save_objects(objects): 
    with open('objects.pkl', 'ab') as output: # Note: `ab` appends the data 
     pickle.dump(objects, output, pickle.HIGHEST_PROTOCOL) 

def Main(): 
    ... 
    #objects=[] <-- lose the objects list 
    with open('links2.txt', 'rb') as infile: 
     for link in infile: 
      ... 
      save_objects(article) 

Sau đó, bạn có thể có từng bước đọc file dưa như vậy:

import pickle 
with open('objects.pkl', 'rb') as pickle_file: 
    try: 
     while True: 
      article = pickle.load(pickle_file) 
      print article 
    except EOFError: 
     pass 

Các lựa chọn tôi có thể nghĩ đến là:

  • Hãy thử cPickle. Nó sẽ giúp.
  • Thử phát trực tuyến-dưa
  • đọc tập tin dưa của bạn trong một môi trường 64-bit với rất nhiều và rất nhiều RAM
  • Re-crawl dữ liệu gốc, lần này thực sự từng bước lưu trữ các dữ liệu, hoặc lưu trữ nó trong một cơ sở dữ liệu . Nếu không có sự không hiệu quả của việc liên tục viết lại tệp đầu ra của bạn, lần thu thập dữ liệu của bạn có thể nhanh hơn đáng kể trong lần này.
+1

cảm ơn một nhóm. Tôi chạy trình thu thập dữ liệu trên một máy tính và sau đó thử xem tệp dưa trên máy khác. Nó hoạt động trên máy ban đầu có nhiều bộ nhớ hơn. –

+5

Ồ, sau đó câu trả lời là hiển nhiên: trích xuất dữ liệu dưới dạng tệp dưa trên máy tính gốc. –

29

Có vẻ như bạn đang uống một chút dưa chua! ;-). Hy vọng rằng sau này, bạn sẽ KHÔNG BAO GIỜ SỬ DỤNG PICKLE EVER. Nó không chỉ là một định dạng lưu trữ dữ liệu rất tốt.

Anyways, cho câu trả lời này, tôi giả định lớp học Document của bạn trông hơi giống thế này.Nếu không, bình luận với lớp Document thực tế của bạn:

class Document(object): # <-- object part is very important! If it's not there, the format is different! 
    def __init__(self, title, date, text): # assuming all strings 
     self.title = title 
     self.date = date 
     self.text = text 

Anyways, tôi thực hiện một số dữ liệu thử nghiệm đơn giản với lớp này:

d = [Document(title='foo', text='foo is good', date='1/1/1'), Document(title='bar', text='bar is better', date='2/2/2'), Document(title='baz', text='no one likes baz :(', date='3/3/3')] 

muối nó với định dạng 2 (pickle.HIGHEST_PROTOCOL cho Python 2.x)

>>> s = pickle.dumps(d, 2) 
>>> s 
'\x80\x02]q\x00(c__main__\nDocument\nq\x01)\x81q\x02}q\x03(U\x04dateq\x04U\x051/1/1q\x05U\x04textq\x06U\x0bfoo is goodq\x07U\x05titleq\x08U\x03fooq\tubh\x01)\x81q\n}q\x0b(h\x04U\x052/2/2q\x0ch\x06U\rbar is betterq\rh\x08U\x03barq\x0eubh\x01)\x81q\x0f}q\x10(h\x04U\x053/3/3q\x11h\x06U\x13no one likes baz :(q\x12h\x08U\x03bazq\x13ube.' 

Và tháo rời nó với pickletools:

>>> pickletools.dis(s) 
    0: \x80 PROTO  2 
    2: ] EMPTY_LIST 
    3: q BINPUT  0 
    5: ( MARK 
    6: c  GLOBAL  '__main__ Document' 
    25: q  BINPUT  1 
    27:)  EMPTY_TUPLE 
    28: \x81  NEWOBJ 
    29: q  BINPUT  2 
    31: }  EMPTY_DICT 
    32: q  BINPUT  3 
    34: (  MARK 
    35: U   SHORT_BINSTRING 'date' 
    41: q   BINPUT  4 
    43: U   SHORT_BINSTRING '1/1/1' 
    50: q   BINPUT  5 
    52: U   SHORT_BINSTRING 'text' 
    58: q   BINPUT  6 
    60: U   SHORT_BINSTRING 'foo is good' 
    73: q   BINPUT  7 
    75: U   SHORT_BINSTRING 'title' 
    82: q   BINPUT  8 
    84: U   SHORT_BINSTRING 'foo' 
    89: q   BINPUT  9 
    91: u   SETITEMS (MARK at 34) 
    92: b  BUILD 
    93: h  BINGET  1 
    95:)  EMPTY_TUPLE 
    96: \x81  NEWOBJ 
    97: q  BINPUT  10 
    99: }  EMPTY_DICT 
    100: q  BINPUT  11 
    102: (  MARK 
    103: h   BINGET  4 
    105: U   SHORT_BINSTRING '2/2/2' 
    112: q   BINPUT  12 
    114: h   BINGET  6 
    116: U   SHORT_BINSTRING 'bar is better' 
    131: q   BINPUT  13 
    133: h   BINGET  8 
    135: U   SHORT_BINSTRING 'bar' 
    140: q   BINPUT  14 
    142: u   SETITEMS (MARK at 102) 
    143: b  BUILD 
    144: h  BINGET  1 
    146:)  EMPTY_TUPLE 
    147: \x81  NEWOBJ 
    148: q  BINPUT  15 
    150: }  EMPTY_DICT 
    151: q  BINPUT  16 
    153: (  MARK 
    154: h   BINGET  4 
    156: U   SHORT_BINSTRING '3/3/3' 
    163: q   BINPUT  17 
    165: h   BINGET  6 
    167: U   SHORT_BINSTRING 'no one likes baz :(' 
    188: q   BINPUT  18 
    190: h   BINGET  8 
    192: U   SHORT_BINSTRING 'baz' 
    197: q   BINPUT  19 
    199: u   SETITEMS (MARK at 153) 
    200: b  BUILD 
    201: e  APPENDS (MARK at 5) 
    202: . STOP 

Trông phức tạp! Nhưng thực sự, nó không quá tệ. pickle về cơ bản là một máy xếp chồng, mỗi mã định danh ALL_CAPS mà bạn nhìn thấy là một mã vạch , thao tác nội bộ "ngăn xếp" theo cách nào đó để giải mã. Nếu chúng tôi đang cố gắng phân tích một số cấu trúc phức tạp, điều này sẽ quan trọng hơn, nhưng may mắn thay, chúng tôi chỉ đang tạo một danh sách đơn giản về các bản chất-tuple. Tất cả "mã" này đang làm là xây dựng một loạt các đối tượng trên ngăn xếp, và sau đó đẩy toàn bộ ngăn xếp vào một danh sách.

Một điều chúng tôi cần quan tâm là các mã 'BINPUT'/'BINGET' bạn thấy nằm rải rác xung quanh. Về cơ bản, đây là để 'ghi nhớ', để giảm bớt dấu chân dữ liệu, pickle lưu các chuỗi với BINPUT <id> và sau đó nếu chúng xuất hiện lại, thay vì bán lại chúng, chỉ cần đặt BINGET <id> để truy xuất chúng từ bộ nhớ cache.

Ngoài ra, một biến chứng khác! Có nhiều hơn chỉ là SHORT_BINSTRING - có bình thường BINSTRING cho chuỗi> 256 byte và cũng có một số biến thể unicode thú vị. Tôi sẽ chỉ giả định rằng bạn đang sử dụng Python 2 với tất cả các chuỗi ASCII. Một lần nữa, hãy bình luận nếu đây không phải là một giả định chính xác.

OK, vì vậy, chúng tôi cần truyền trực tuyến tệp cho đến khi chúng tôi đạt đến '\ 81' byte (NEWOBJ). Sau đó, chúng ta cần phải quét trước cho đến khi chúng ta nhấn ký tự '(' (MARK). Sau đó, cho đến khi chúng ta nhấn 'u' (SETITEMS), chúng ta đọc các cặp chuỗi khóa/giá trị - sẽ có tổng cộng 3 cặp, một cho Vì vậy, hãy làm điều này.Đây là kịch bản của tôi để đọc dữ liệu dưa trong thời trang trực tuyến. Nó hoàn hảo, vì tôi chỉ hack nó với nhau cho câu trả lời này, và bạn sẽ cần phải sửa đổi nó rất nhiều, nhưng đó là một khởi đầu tốt

pickledata = '\x80\x02]q\x00(c__main__\nDocument\nq\x01)\x81q\x02}q\x03(U\x04dateq\x04U\x051/1/1q\x05U\x04textq\x06U\x0bfoo is goodq\x07U\x05titleq\x08U\x03fooq\tubh\x01)\x81q\n}q\x0b(h\x04U\x052/2/2q\x0ch\x06T\x14\x05\x00\x00bar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterq\rh\x08U\x03barq\x0eubh\x01)\x81q\x0f}q\x10(h\x04U\x053/3/3q\x11h\x06U\x13no one likes baz :(q\x12h\x08U\x03bazq\x13ube.' 

# simulate a file here 
import StringIO 
picklefile = StringIO.StringIO(pickledata) 

import pickle # just for opcode names 
import struct # binary unpacking 

def try_memo(f, v, cache): 
    opcode = f.read(1) 
    if opcode == pickle.BINPUT: 
     cache[f.read(1)] = v 
    elif opcode == pickle.LONG_BINPUT: 
     print 'skipping LONG_BINPUT to save memory, LONG_BINGET will probably not be used' 
     f.read(4) 
    else: 
     f.seek(f.tell() - 1) # rewind 

def try_read_string(f, opcode, cache): 
    if opcode in [ pickle.SHORT_BINSTRING, pickle.BINSTRING ]: 
     length_type = 'b' if opcode == pickle.SHORT_BINSTRING else 'i' 
     str_length = struct.unpack(length_type, f.read(struct.calcsize(length_type)))[0] 
     value = f.read(str_length) 
     try_memo(f, value, memo_cache) 
     return value 
    elif opcode == pickle.BINGET: 
     return memo_cache[f.read(1)] 
    elif opcide == pickle.LONG_BINGET: 
     raise Exception('Unexpected LONG_BINGET? Key ' + f.read(4)) 
    else: 
     raise Exception('Invalid opcode ' + opcode + ' at pos ' + str(f.tell())) 

memo_cache = {} 
while True: 
    c = picklefile.read(1) 
    if c == pickle.NEWOBJ: 
     while picklefile.read(1) != pickle.MARK: 
      pass # scan forward to field instantiation 
     fields = {} 
     while True: 
      opcode = picklefile.read(1) 
      if opcode == pickle.SETITEMS: 
       break 
      key = try_read_string(picklefile, opcode, memo_cache) 
      value = try_read_string(picklefile, picklefile.read(1), memo_cache) 
      fields[key] = value 
     print 'Document', fields 
     # insert to sqllite 
    elif c == pickle.STOP: 
     break 

này đọc một cách chính xác dữ liệu thử nghiệm của tôi trong định dạng dưa 2 (sửa đổi để có một chuỗi dài):.

$ python picklereader.py 
Document {'date': '1/1/1', 'text': 'foo is good', 'title': 'foo'} 
Document {'date': '2/2/2', 'text': 'bar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is betterbar is better', 'title': 'bar'} 
Document {'date': '3/3/3', 'text': 'no one likes baz :(', 'title': 'baz'} 

Chúc bạn may mắn!

Các vấn đề liên quan