我知道这已被多次询问,但我的问题不同,因为我使用的是第三方代码而且无法修改太多。 我有一个在代码中多次调用的函数来创建子进程,将数据写入stdin然后读取。它只是挂在这一行
line = self.classifier.stderr.readline()
使用popen.communicate确实解决了这个问题,但由于需要多次调用func2(分类器,向量),它会引发异常
subprocess I/O operation on closed file
有没有办法执行非阻塞读取操作?
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)
修改代码以添加更多详细信息
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 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 :(得分:0)
压痕?在func2做任何事情之前,看起来func1退出并带有一个return语句。将所有内容从func2一个选项卡向左移动,看看会发生什么。或者,问题可能在其他地方 - 您只是没有正确粘贴代码。
答案 1 :(得分:0)
这是你的答案(来自https://docs.python.org/2/library/subprocess.html)吗? 注意请勿对此函数使用stdout = PIPE或stderr = PIPE,因为这可能会基于子进程输出卷死锁。需要管道时,请使用Popen和communic()方法。
答案 2 :(得分:0)
你说你不能更改代码,但也许你可以稍微改变它:)尝试编写一个块,找出正在使用哪个“向量”并使用另一个。