我编写了以下用于执行snt2cooc命令的函数(运行GIZA++的预处理步骤之一。出于我们的目的,我认为我们可以将snt2cooc脚本视为一个黑匣子):
func SNTToCOOC(srcVocab, tgtVocab, sntPath, outpath string) error {
// open the out file for writing
outfile, err := os.Create(outpath)
if err != nil {
return err
}
defer outfile.Close()
cmdStr := "snt2cooc"
args := []string{srcVocab, tgtVocab, sntPath}
cmd := exec.Command(cmdStr, args...)
cmd.Stdout = outfile
if err = cmd.Run(); err != nil {
return err
}
cmd.Wait()
return err
}
运行时,函数执行没有错误,但输出文件为空。相同的代码适用于其他类似的命令,但不适用于此特定snt2cooc命令,我注意到当我直接在 shell 中运行此命令时:
snt2cooc file1.vcb file2.vcb file3.snt
我得到以下输出:
END.
0 2
0 3
0 4
0 5
0 6
(为简洁起见被截断)
如果我直接从 shell 将命令的输出发送到一个文件:
snt2cooc file1.vcb file2.vcb file3.snt > out.txt
内容out.txt如预期:
0 2
0 3
0 4
0 5
0 6
请注意,在第一种情况下,该行END.首先输出到 stdout,然后才是发送到 stdout 的命令的实际输出。因此,我认为存在竞争条件,即 Go 代码在命令的最终输出写入文件之前完成执行。这尽管调用cmd.Wait(). 我不太确定该snt2cooc命令在内部究竟在做什么。有人可以提供有关如何解决此问题的提示吗?
编辑1:
看起来像下面的代码,包括 500 毫秒的睡眠,一致地将输出写入snt2cooc命令的文件:
cmdStr := "snt2cooc"
args := []string{srcVocab, tgtVocab, sntPath}
cmd := exec.Command(cmdStr, args...)
stdout, err := cmd.StdoutPipe()
time.Sleep(500 * time.Millisecond)
if err != nil {
return err
}
err = cmd.Start()
if err != nil {
return err
}
out := bufio.NewScanner(stdout)
for out.Scan() {
outfile.Write(out.Bytes())
outfile.WriteString("\n")
}
if err := out.Err(); err != nil {
return err
}
这向我证明存在一些竞争条件,Go 程序在所有输出写入文件之前退出。我为这个问题增加了悬赏,希望有人可以 1) 解释为什么会发生这种情况,2) 提供一种非 hacky 的方式(即 500 毫秒睡眠)来解决它。
撒科打诨
HUWWW
相关分类