【发布时间】:2014-01-30 18:27:44
【问题描述】:
我想从 Haskell 运行一个外部程序并检索其输出和错误流的内容。在其中一个库中,我找到了以下代码:
runProcess :: FilePath -> [String] -> IO (ExitCode, String, String)
runProcess prog args = do
(_,o,e,p) <- runInteractiveProcess prog args Nothing Nothing
hSetBuffering o NoBuffering
hSetBuffering e NoBuffering
sout <- hGetContents o
serr <- hGetContents e
ecode <- length sout `seq` waitForProcess p
return (ecode, sout, serr)
这是正确的做法吗?
这里有一些我不明白的地方:为什么流设置为NoBuffering?为什么length sout `seq`?这感觉像是某种黑客行为。
另外,我想将输出和错误流合并为一个,以获得与在命令行上执行2>&1 相同的效果。如果可能,我想避免使用专用的 I/O 库并依赖 GHC 提供的标准包。
【问题讨论】:
-
我不确定是否可以获得与在 shell 中执行
2>&1相同的效果。你有什么特别的理由想要这样吗? -
我想说
seq的原因是强制消耗程序的完整输出。否则(因为字符串是惰性的)可能会发生死锁:子进程将等待写入其输出,而主进程将等待进程完成。但似乎serr可能存在同样的问题,我担心如果程序将大量输出写入其标准错误,上述代码也会挂起。做到这一点可能不会很简单,所以我可能宁愿寻找一些已经解决问题的稳定 IO 库。 -
您还需要程序是多平台的,还是针对特定平台?
-
process库有函数readProcessWithExitCode以字符串形式返回stdout和stderr。如果进程写入大量输出,如果您想在程序运行时访问输出,或者如果您希望stdout和stderr交错,那么这还不够。 -
如果您使用
runProcess并为stdout 和stderr 传递相同的句柄(而不是Nothing),它应该像2>&1一样工作。