2016-11-09 3 views
0

제 3 자 코드를 사용하면서 너무 많이 수정할 수는 없지만 여러 번 질문했지만 제 문제가 다릅니다. 코드에서 여러 번 호출되어 하위 프로세스를 만들고 stdin에 데이터를 쓰고 읽는 함수가 있습니다. 그것은 단지는 popen with python 읽기 및 쓰기 블록, python2.7

subprocess I/O operation on closed file 
거기가 예외가 발생,이 라인

line = self.classifier.stderr.readline() 

이 문제를 해결하지만, FUNC2 (분류, 벡터)부터하는 것은 여러 번 호출 할 필요가 않았다 popen.communicate을 사용하여에 달려 비 차단 읽기 작업을 수행하는 방법은 무엇입니까? 자세한

import subprocess 
import paths 
import os.path 

class CRFClassifier: 
    def __init__(self, name, model_type, model_path, model_file, verbose): 
     self.verbose = verbose 
     self.name = name 
     self.type = model_type 
     self.model_fname = model_file 
     self.model_path = model_path 

     if not os.path.exists(os.path.join(self.model_path, self.model_fname)): 
      print 'The model path %s for CRF classifier %s does not exist.' % (os.path.join(self.model_path, self.model_fname), name) 
      raise OSError('Could not create classifier subprocess') 


     self.classifier_cmd = '%s/crfsuite-stdin tag -pi -m %s -' % (paths.CRFSUITE_PATH, 
          os.path.join(self.model_path, self.model_fname)) 
#  print self.classifier_cmd 
     self.classifier = subprocess.Popen(self.classifier_cmd, shell = True, stdin = subprocess.PIPE, stderr = subprocess.PIPE) 

     if self.classifier.poll(): 
      raise OSError('Could not create classifier subprocess, with error info:\n%s' % self.classifier.stderr.readline()) 

     #self.cnt = 0 


    def classify(self, vectors): 
#  print '\n'.join(vectors) + "\n\n" 

     self.classifier.stdin.write('\n'.join(vectors) + "\n\n") 

     lines = [] 
     line = self.classifier.stderr.readline() 
     while (line.strip() != ''): 
#   print line 
      lines.append(line) 
      line = self.classifier.stderr.readline() 


     if self.classifier.poll(): 
      raise OSError('crf_classifier subprocess died') 

     predictions = [] 
     for line in lines[1 : ]: 
      line = line.strip() 
#   print line 
      if line != '': 
       fields = line.split(':') 
#    print fields 
       label = fields[0] 
       prob = float(fields[1]) 
       predictions.append((label, prob)) 

     seq_prob = float(lines[0].split('\t')[1]) 

     return seq_prob, predictions 


    def poll(self): 
     """ 
     Checks that the classifier processes are still alive 
     """ 
     if self.classifier is None: 
      return True 
     else: 
      return self.classifier.poll() != None 

분류기 개체가 또한 실행 문장들의리스트와 생성시 문서 인 입력 파일에 대한 생성을 추가 할 수있는 코드를 수정

def func1 (extcmd): 
       cmd=extcmd 
       classifier = subprocess.Popen(self.classifier_cmd, shell = True, stdin = subprocess.PIPE, stderr = subprocess.PIPE) 
       if self.classifier.poll(): 
        raise OSError('Could not create classifier subprocess') 
       return classifier 

def func2(classifier, vectors): 
         classifier.stdin.write('\n'.join(vectors) + "\n\n") 
         lines = [] 
         line = self.classifier.stderr.readline() 
         print("not reaching") 
         while (line.strip() != ''): 
       #   print line 
          lines.append(line) 
          line = self.classifier.stderr.readline() 

if __name__ == '__main__': 
       extcmd="some external shell script" 
       vectors="some results" 
       classifier=func1(extcmd) 
       func2(classifier, vectors) 

이 문장 목록을 가진 외부 명령. 그런 다음 별도의 함수에서 모든 문장이 처리되어 각 문장마다 별도의 벡터가 제공됩니다. 이 새로운 벡터는 분류 함수에 전달됩니다.

def func2(): 
    classifier=create a classifier object for an input file, this executes the external command 
    for sentence in sentences: 
     vectors=process(sentence)# some external function 
     classifier.classify(features)      
+0

부끄러워 플러그 : https://github.com/TeamHG-Memex/sklearn-crfsuite 유용한 찾을 수 있습니다; crfsuite 명령 줄을 래핑하는 것보다 쉬워야합니다. –

답변

0

들여 쓰기? func2가 무엇인가를하기 전에 return 문으로 func1을 종료하는 것처럼 보입니다. func2 한 탭에서부터 왼쪽으로 모든 것을 옮기고 무슨 일이 일어나는 지보십시오. 아니면 문제가 다른 곳에있을 수도 있습니다 - 코드를 올바르게 붙여 넣지 않았습니까?

+0

죄송합니다. 나는 그것을 지금 제대로 포맷했다. 문제는 교착 상태 때문에 발생하지만 func2는 여러 번 호출되기 때문에 통신을 사용할 수 없습니다. – AMisra

0

답변입니까 (https://docs.python.org/2/library/subprocess.html)? 참고 자식 프로세스 출력 볼륨을 기반으로 교착 상태가 발생할 수 있으므로 stdout = PIPE 또는 stderr = PIPE를이 함수와 함께 사용하지 마십시오. 파이프가 필요할 때 Popen을 communicate() 메소드와 함께 사용하십시오.

+1

예, 통신 작업을 처음으로 읽었지만 func2가 두 번 이상 호출되었으며 통신하는 경우 두 번째 오류 인 ValueError : 닫힌 파일에 대한 I/O 작업이 실패합니다. 내가 사용할 수있는 선택에 대해 읽고 있는데, 나는 물건을 엉망으로 만들지 않고 그것을 어떻게 사용할 수 있을지 모르겠다. – AMisra

0

당신은 코드를 많이 변경할 수는 없지만 약간 변경할 수 있다고 했지요. 어떤 "벡터"가 사용되고 있는지를 알아 내고 다른 블록을 사용하십시오.

+0

큰 코드베이스이므로 수정하기가 너무 힘들었고 어떤 영향을 미칠지 잘 모르겠습니다. 벡터에 대해 말할 때 좀 더 설명하거나 예제를 가리켜 주시겠습니까? 나는 코드를 디버깅했으며 이것이 어떻게 작동 하는지를 설명한다. func1은 문장 목록으로 명령을 실행합니다. 그런 다음 func2를 모든 문장 입력에 대해 벡터로 반복하여 호출하여 결과를 읽습니다. 따라서 통신을 사용하고 오류가있는 경우 첫 번째 문장에서 작동합니다. – AMisra

+0

func1에서 "cmd"는 어떻게 사용됩니까? – postoronnim

+0

코드 사용 방법을 보여주기 위해 더 많은 코드를 추가했습니다. – AMisra