2016-09-11 4 views
1

protobuf에서 결과를 출력하고 싶습니다. (크기가 훨씬 작으므로) 결과를 파이썬으로 다시 읽으 려합니다. 어떻게해야합니까?Protobuf Python에서 StanfordNLP 출력의 직렬화

java -cp "stanford-corenlp-full-2015-12-09/*" \ 
edu.stanford.nlp.pipeline.StanfordCoreNLP \ 
-annotators tokenize,ssplit \ 
-file input.txt \ 
-outputFormat serialized \ 
-outputSerializer \ 
edu.stanford.nlp.pipeline.ProtobufAnnotationSerializer 

다음이 추천 파이썬 모듈로 StanfordNLP의 소스 코드와 함께 제공되는 CoreNLP.proto, 컴파일 protoc을 사용

는 I는 출력 명령 here 이런 ProtobufAnnotationSerializer 직렬화 결과를 따랐다

protoc --python_out=. CoreNLP.proto 

그런 다음 파이썬에서 나는 다음과 같은 파일을 다시 읽어 :

import CoreNLP_pb2 
doc = CoreNLP_pb2.Document() 
doc.ParseFromString(open('input.txt.ser.gz', 'rb').read()) 

구문 분석은 다음과 같은 오류 메시지와 함께 실패

--------------------------------------------------------------------------- 
DecodeError        Traceback (most recent call last) 
<ipython-input-213-d8eaeb9c2048> in <module>() 
     1 doc = CoreNLP_pb2.Document() 
----> 2 doc.ParseFromString(open('imed/s5_tokenized/conv-00000.ser.gz', 'rb').read()) 

/usr/local/lib/python2.7/dist-packages/google/protobuf/message.pyc in ParseFromString(self, serialized) 
    183  """ 
    184  self.Clear() 
--> 185  self.MergeFromString(serialized) 
    186 
    187 def SerializeToString(self): 

/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/python_message.pyc in MergeFromString(self, serialized) 
    1092   # The only reason _InternalParse would return early is if it 
    1093   # encountered an end-group tag. 
-> 1094   raise message_mod.DecodeError('Unexpected end-group tag.') 
    1095  except (IndexError, TypeError): 
    1096  # Now ord(buf[p:p+1]) == ord('') gets TypeError. 

DecodeError: Unexpected end-group tag. 

UPDATE :

내가 시리얼 가버 안젤리의 저자를 요구하고 대답을 얻었다. protobuf 개체는 writeDelimitedTo 인 파일에 this line으로 기록되었습니다. writeTo으로 변경하면 출력 파일을 Python으로 읽을 수 있습니다.

+0

실행중인 protoc의 버전은 무엇입니까? 'protoc --version' – sberry

+0

@sberry : "libprotoc 3.0.0"을 출력합니다. – shaoyl85

+0

그게 문제 일 수도 있습니다. (.java 파일을 생성하는 데 사용 된 버전이 무엇인지는 모르겠지만) 문제가 너무 많아서 제 대답을 먼저보십시오. – sberry

답변

2

이 질문이 다시 떠오른 것처럼 보였으므로 적절한 대답을 적어 두었습니다. 이 문제의 근본 원인은 proto가 Java의 writeDelimitedTo 메소드를 사용하여 작성 되었기 때문입니다. Google은 Python을 구현하지 않았습니다.

from google.protobuf.internal.decoder import _DecodeVarint 
import CoreNLP_pb2 

def readCoreNLPProtoFile(protoFile): 
    protos = [] 
    with open(protoFile, 'rb') as f: 
    # -- Read the file -- 
    data = f.read() 
    # -- Parse the file -- 
    # In Java. there's a parseDelimitedFrom() method that makes this easier 
    pos = 0 
    while (pos < len(data)): 
     # (read the proto) 
     (size, pos) = _DecodeVarint(data, pos) 
     proto = CoreNLP_pb2.Document() 
     proto.ParseFromString(data[pos:(pos+size)]) 
     pos += size 
     # (add the proto to the list; or, `yield proto`) 
     protos.append(proto) 
    return protos 

파일 CoreNLP_pb2은 다음과 같습니다 - 해결 방법은 (당신이 적절하게 파일을 압축 해제 적절한 코드로 f.read()를 대체 할 수있는 파일이 gziped되지 않은 가정) 프로토 파일을 읽을 수있는 다음과 같은 방법을 사용하는 것입니다 다음 명령을 사용하여 REPO에 CoreNLP.proto 파일에서 컴파일이 (버전 3.7.0)를 작성하는대로 형식이 proto2하지 proto3입니다

protoc --python_out /path/to/output/ /path/to/CoreNLP.proto 

하는 것으로.

관련 문제