我寫了下面的函數用於執行snt2cooc
命令(的預處理步驟之一運行GIZA++。對於我們而言,我認爲我們可以考慮snt2cooc
腳本是一個黑色的盒):未能編寫shell命令的輸出到文件中去
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
(截斷簡潔)
如果我直接在命令的輸出發送到一個文件從外殼:
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)提供一種非破解的方式(即500ms睡眠)來修復它。
您是否在運行後關閉文件之前嘗試調用['Sync'](https://golang.org/pkg/os/#File.Sync)? –
@ Ainar-G我現在試過了,它似乎沒有效果。 –
而'Sync'也不會返回任何錯誤?如果將'bytes.Buffer'設置爲stdout,然後在運行後打印緩衝區的內容,它是否也是空的? –