2011-03-31 3 views
8

당신에게 문맥을주기 위해서 :여러 개의 Python 절편 데이터를 한 번에 읽고 버퍼링하고 줄 바꿈?

나는 큰 파일 f을 몇 기가 크기로 가지고있다. 내가이 파일을 읽을 때 버퍼링을 활용하려는

for obj in objs: cPickle.dump(obj, f)

를 실행하여 생성 된 다른 객체의 연속 피클이 포함되어 있습니다. 내가 원한 것은 여러 개의 픽업 된 오브젝트를 한 번에 버퍼로 읽는 것입니다. 이 일을하는 가장 좋은 방법은 무엇입니까? 피킹 된 데이터에 대해서는 의 아날로그가 필요합니다. 실제로 선택된 데이터가 실제로 개행 문자로 분리 된 경우 readline을 사용할 수 있지만 사실인지 확실하지 않습니다.

내가 염두에두고있는 또 다른 옵션은 절편 객체를 먼저 문자열로 채운 다음 파일에 문자열을 쓰는 것입니다. 각각은 개행 문자로 구분됩니다. 파일을 다시 읽으려면 readlines()loads()을 사용할 수 있습니다. 하지만 절인 된 물체가 "\n" 문자를 가질 수 있으며이 파일 읽기 체계를 버릴까 봐 걱정됩니다. 내 두려움은 근거가 없습니까?

하나의 옵션은 객체의 거대한 목록으로 피클 링하는 것이지만, 그럴 수있는 것보다 많은 메모리가 필요합니다. 멀티 스레딩으로 속도를 높일 수는 있지만 버퍼링이 제대로 작동하기 전에 거기에 가고 싶지 않습니다. 이와 같은 상황에 대한 "우수 사례"는 무엇입니까?

EDIT : 또한 원시 바이트를 버퍼로 읽어 들여로드를 호출 할 수 있지만, 버퍼를 얼마나 많이 사용했는지 알 필요가 있으므로 헤드를 버릴 수 있습니다.

+1

이미 장면 뒤에서 버퍼링이 발생해야합니다. 또한 스레드가 도움이되지 않습니다. –

+0

pickle 파일의 생성을 제어 할 수 있다면,'pickle.dump (obj, f, pickle.HIGHEST_PROTOCOL)'(또는 이와 동등한'pickle.dump (obj, f, -1)')로, 바이너리 프로토콜이며 디폴트 ASCII보다 훨씬 더 작습니다. 파일 크기가 훨씬 작 으면 버퍼링에 대한 우려를 줄일 수 있습니다. 실제로 "@Kirk Strauser의 [answer] (http://stackoverflow.com/a/5507750/355230)에서". \ n "'"트릭으로 끝나는 라인을 찾는 것이 효과가 없을 것입니다. – martineau

답변

5

file.readlines() 파일의 전체 내용 목록을 반환합니다. 한 번에 몇 줄을 읽고 싶을 것입니다. 나는이 순진 코드는 데이터를 unpickle해야한다고 생각 :

  1. 사용 shelve 모듈 : 당신은 피클을 생성하는 프로그램에 대한 제어가있는 경우

    import pickle 
    infile = open('/tmp/pickle', 'rb') 
    buf = [] 
    while True: 
        line = infile.readline() 
        if not line: 
         break 
        buf.append(line) 
        if line.endswith('.\n'): 
         print 'Decoding', buf 
         print pickle.loads(''.join(buf)) 
         buf = [] 
    

    , 나는 중 하나를 선택할 것입니다.

  2. 각 피클의 길이 (바이트)를 파일에 기록하기 전에 인쇄하여 매번 정확히 읽을 바이트 수를 알 수 있도록하십시오.
  3. 위와 같지만 정수 목록을 별도의 파일에 쓰면 해당 값을 피클을 담고있는 파일의 색인으로 사용할 수 있습니다.
  4. 한 번에 K 개의 개체 목록을 선택하십시오. 해당 피클의 길이를 바이트로 씁니다. 피클을 씁니다. 반복.

그건 그렇고, 나는 file의 내장 버퍼링이 당신이 찾고있는 성능 향상의 99 %를 가져야한다고 생각합니다.

I/O가 차단하고 있다고 확신하는 경우 mmap()을 시도하고 OS에서 한 번에 블록 단위로 처리하도록 고려 했습니까?당신이 어떤 파일에 버퍼링을 추가하려면

#!/usr/bin/env python 

import mmap 
import cPickle 

fname = '/tmp/pickle' 
infile = open(fname, 'rb') 
m = mmap.mmap(infile.fileno(), 0, access=mmap.ACCESS_READ) 
start = 0 
while True: 
    end = m.find('.\n', start + 1) + 2 
    if end == 1: 
     break 
    print cPickle.loads(m[start:end]) 
    start = end 
+0

이것은 필자가 읽은 바이트 수에 미리 지정된 제한으로 readllines를 사용하는 것을 제외하고는 필자가 가지고있는 솔루션과 매우 비슷합니다. 그것이 내가 알고 싶은 비판적 비트입니다. 그렇지 않으면 우리는 버그 투성이입니다. 개인 피클이 ". \ n"으로 끝나는 것을 정확하게 읽었습니까? 다시 말하면 개행 다음에 개가 오는 것입니까? 다른 제안을 주셔서 감사합니다. 지금은 버퍼링 된 파일 객체에 대해 cPickle.load()를 계속 호출하고 avg에서 약 800 바이트에 약 200 개의 객체/초를 읽을 수 있습니다. – san

+0

나는 전문가는 아니지만 데이터베이스 테이블을 살펴보면 몇 천개의 피클을 넣을 수 있으며 모두 '. \ n'로 끝납니다. 'pickle.dumps ('\ n')'을 보라; 비록 그것이 보장되는지는 모르지만 그것은 '\ n'을 벗어나는 것처럼 보인다. # 4에 대해 어떻게 생각하니 목록에서 많은 항목을 pickle 한 다음 하나의 file.read()에서 압축을 풉니 다? –

+0

예 # 4가 좋습니다. 단점은 소비자가 고정 '버퍼'에 제약을 받는다는 것입니다. 그러나 당신이 ". \ n"에 대해 말한 것이 정확하다면 문제는 이미 해결되어 있습니다 :) – san

2

shelve 모듈을 살펴볼 수 있습니다. 데이터베이스의 모듈 (예 : dbm)을 사용하여 개체의 디스크 사전을 만듭니다. 객체 자체는 여전히 pickle을 사용하여 직렬화됩니다. 그렇게하면 한 번에 하나의 큰 피클 대신 여러 개의 물체를 읽을 수 있습니다.

+0

답장을 보내 주셔서 감사합니다. 나는 이것이 어떻게 더 효율적인 버퍼링에 도움이되는지 볼 수 없다. 내가 찾고있는 것은 대량의 바이트를 읽고 한 번에'K' 객체를 언 피클 (unpickle)하는 방법이다. 아이디어는 I/O 병목 현상을 완화하는 것입니다. 나는 당신이 제안하는 것이 내가 많은 키를 제공함으로써 많은 수의 객체를로드하려고 시도한다는 것을 믿는다. 그런 다음 모듈은 해당 키에 해당하는 값을 찾습니다. Islo은 많은 수사와 그에 따른 한 걸음 뒤로 물러나는 것입니다. 제가 물건의 순서를 신경 쓰지 않는다는 것입니다. 하지만 내가 너를 잘못 잡았을거야. – san

2

, io.open()를 통해 엽니 다. 다음은 128K 청크의 기본 스트림에서 읽는 예제입니다. 가 소진 될 때까지 cPickle.load()를 호출 할 때마다이 내부 버퍼에서 성취 될 것이다, 그 다음 또 다른 덩어리는 기본 파일에서 읽을 수 있습니다 :

import cPickle 
import io 

buf = io.open('objects.pkl', 'rb', buffering=(128 * 1024)) 
obj = cPickle.load(buf) 
+0

정확히 내가하는 일은 버퍼 된 인터페이스를 사용하여 gzip 압축 (압축 수준 2) 파일을 읽었지만 기대했던 것입니다. 가능한 한 많은 피클 링 된 오브젝트를 효율적으로 가져올 수 있습니다. 그래서 내가 얻는 피드백은 이것이 스레딩되지 않으면 이것이 얼마나 빨라질 수 있다는 것입니다. – san

6

당신은 아무것도 할 필요가 없습니다, 나는 생각한다.

>>> import pickle 
>>> import StringIO 
>>> s = StringIO.StringIO(pickle.dumps('apples') + pickle.dumps('bananas')) 
>>> pickle.load(s) 
'apples' 
>>> pickle.load(s) 
'bananas' 
>>> pickle.load(s) 

Traceback (most recent call last): 
    File "<pyshell#25>", line 1, in <module> 
    pickle.load(s) 
    File "C:\Python26\lib\pickle.py", line 1370, in load 
    return Unpickler(file).load() 
    File "C:\Python26\lib\pickle.py", line 858, in load 
    dispatch[key](self) 
    File "C:\Python26\lib\pickle.py", line 880, in load_eof 
    raise EOFError 
EOFError 
>>> 
관련 문제