2016-11-09 5 views
0

私はこれが何度も尋ねられていますが、私の問題は私がサードパーティのコードを使用していて、それをあまりにも多く変更することはできないことを知っています。 サブプロセスを作成し、stdinにデータを書き込んだり読み込んだりするために、コード内で何度も呼び出される関数があります。それはちょうど、この問題を解決しましたが、関数func2(クラシファイア、ベクトル)が複数回呼び出される必要があるため、それが例外をスローpopenのpython読み書きブロックpython2.7

subprocess I/O operation on closed file 

はありpopen.communicateを使用して、このラインで

line = self.classifier.stderr.readline() 

をハング非ブロッキング読み出し操作を実行する方法?

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から始まるものすべてを1つのタブから左に移動して何が起こるかを見てください。あるいは、おそらく問題が他の場所にあるかもしれません - コードを正しく貼り付けなかっただけです。

+0

私は今それを正しくフォーマットしました。私は問題がデッドロックの原因であることを知っていますが、func2が複数回呼び出されているので通信できません。 – AMisra

0

これはあなたの答えですか(https://docs.python.org/2/library/subprocess.html)? 注意この関数でstdout = PIPEまたはstderr = PIPEを使用しないでください。子プロセス出力ボリュームに基づいてデッドロックする可能性があります。 pipeが必要なときはPopenを使って、()メソッドを呼び出してください。

+1

はい、最初に通信作業を読み込んで使用していますが、func2が複数回呼び出されています。通信を使用すると、エラーで2回失敗します。ValueError:閉じられたファイルに対するI/O操作。私は使用できる選択について読んでいるが、どうすればそれを使いこなすことができるのか分からない。 – AMisra

0

コードを大きく変更することはできませんが、多少変更することができます。「ベクター」が使用されていることを確認し、別のブロックを使用してください。

+0

私はそれが大きなコードベースであるので、あまりにもそれを変更することには消極的でした、そして、私はそれがどんな影響を持っているか分かりません。あなたはそれについてもう少し説明するか、ベクトルについて言うときにいくつかの例を指摘してください。私はコードをデバッグし、これはどのように動作します。 func1は、文のリストを含むコマンドを実行します。次に、func2は、文を入力するたびに反復的に呼び出され、結果を読み込みます。したがって、通信を使用してエラーが発生した場合、最初のセンテンスで動作します。 – AMisra

+0

func1で「cmd」はどのように使用されていますか? – postoronnim

+0

どのように使用されているかを示すためにコードを追加しました – AMisra

関連する問題