4

プロセスを作成し、haskell プログラムからプロセスの stdin に定期的に (IO アクションから) テキストを書き込みたいと考えています。

以下は GHCi では正しく動作しますが、ビルドして実行すると正しく動作しません。GHCi ではすべてが完璧に機能し、IO アクションからの値が定期的に供給されます。ただし、ビルドして実行すると、プロセスの標準入力に書き込むときに、任意の長い期間一時停止するようです。

CreateProcess(から) を使用System.Processしてハンドルを作成し、試しましたhPutStrLn(bufferent をNoBuffering--に設定しても機能しませんでしたLineBuffering)。

process-streamingそのため、パッケージを試していますpipesが、まったく機能しないようです。

本当の問題はこれです: haskell からプロセスを作成し、定期的に書き込むにはどうすればよいですか?

この動作を示す最小限の例:

import System.Process
import Data.IORef
import qualified Data.Text as T  -- from the text package
import qualified Data.Text.IO as TIO
import Control.Concurrent.Timer  -- from the timers package
import Control.Concurrent.Suspend -- from the suspend package

main = do
    (Just hin, _,_,_) <- createProcess_ "bgProcess" $
        (System.Process.proc "grep"  ["10"]) { std_in = CreatePipe }

    ref <- newIORef 0 :: IO (IORef Int)
    flip repeatedTimer (msDelay 1000) $ do
        x <- atomicModifyIORef' ref $ \x -> (x + 1, x)
        hSetBuffering hin NoBuffering
        TIO.hPutStrLn hin $ T.pack $ show x

どんな助けでも大歓迎です。

4

2 に答える 2

3

Producerこれは、2 番目の遅延で一連の数値を出力するパイプです。

{-# language NumDecimals #-}
import Control.Concurrent
import Pipes
import qualified Data.ByteString.Char8 as Bytes

periodic :: Producer Bytes.ByteString IO ()
periodic = go 0
    where
        go n = do
            d <- liftIO (pure (Bytes.pack (show n ++ "\n"))) -- put your IO action here
            Pipes.yield d
            liftIO (threadDelay 1e6)
            go (succ n)

そして、process-streamingを使用して、次のようにプロデューサーを外部プロセスにフィードできます。

import System.Process.Streaming

main :: IO ()
main = do
    executeInteractive (shell "grep 10"){ std_in = CreatePipe } (feedProducer periodic)

に自動的にexecuteInteractive設定される を使用しました。std_inNoBuffering

また、パイプstd_outを使用して各一致をすぐに処理したい場合は、--line-bufferedオプションを grep に渡して (またはstdbufコマンドを使用して)、一致が出力ですぐに利用できるようにしてください。

于 2016-05-25T21:59:55.730 に答える