通过管道(在Python中)将Haskell程序连接到Python程序

通过管道(在Python中)将Haskell程序连接到Python程序,python,user-interface,haskell,pipeline,Python,User Interface,Haskell,Pipeline,请容忍我,因为我对编程相当陌生。我的基本问题是。我有一个用Haskell编写的程序,我想把它的stdout连接到Python程序的stdin(它将管理GUI相关的东西)。类似地,我想将Python程序的stdout连接到Haskell程序的stdin,这样它就可以向Haskell程序发送有关用户单击/键入内容的信息 第一个问题是,如果我在两者之间建立一个管道,假设Python程序的stdout连接到Haskell程序,如果我使用Tkinter创建小部件和东西,它们会显示在屏幕上吗 第二个问题是,

请容忍我,因为我对编程相当陌生。我的基本问题是。我有一个用Haskell编写的程序,我想把它的stdout连接到Python程序的stdin(它将管理GUI相关的东西)。类似地,我想将Python程序的stdout连接到Haskell程序的stdin,这样它就可以向Haskell程序发送有关用户单击/键入内容的信息


第一个问题是,如果我在两者之间建立一个管道,假设Python程序的stdout连接到Haskell程序,如果我使用Tkinter创建小部件和东西,它们会显示在屏幕上吗

第二个问题是,我将如何建立这条管道?考虑下面的示例代码…

main :: IO ()
main = do
    -- putStrLn "Enter a number." <- this will be displayed in Python
    string <- getLine
    putStrLn $ 5 + read string::Int -- or any equivalent function to send to stdout
main::IO()
main=do

--putStrLn“输入一个数字。”您还可以通过命令shell建立管道:

mypython.py | myhaskell.hs

Haskell计划的响应将与 任何其他类型的标准输入,如:

我使用myhaskell.hs实现它,因为它提供了对轮询的强大抽象。基本上,您需要首先定义Python和Haskell程序相互通信的方式(在Twisted中称为协议),例如,数据包的长度、如何处理错误等。然后您只需对它们进行编码

以下是haskell代码:

-- File "./Hs.hs"

import Control.Concurrent                                                   
import System.IO

main = do
  -- Important
  hSetBuffering stdout NoBuffering

  -- Read a line
  line <- getLine

  -- parse the line and add one and print it back
  putStrLn (show (read line + 1))

  -- Emphasize the importance of hSetBuffering :P
  threadDelay 10000000
--文件“/Hs.Hs”
导入控制。并发
导入系统.IO
main=do
--重要的
hSetBuffering标准输出无缓冲
--读一行

行“如果我在两者之间设置一个管道,假设Python程序的stdout连接到Haskell程序,如果我使用Tkinter创建小部件和东西,它们会显示在屏幕上吗?”-试试看?只要注意不要通过读取Haskell进程来阻塞Tk事件循环运行的线程,它就应该可以工作。如果您可以从Python执行Haskell程序,而不是相反的方式,或者(更糟糕的是)尝试连接两个独立运行的程序,那么这可能是最简单的。非常感谢!我将尝试从子流程模块开始。:)关于子流程模块中的哪些函数/方法,您有什么建议吗?大多数人建议不要使用stdin=PIPE或stdout=PIPE等,我认为在本例中这样做是正确的。请确保在Haskell中使用
hSetBuffering stdout NoBuffering
(例如,在
main
的开头)。否则,块缓冲将阻止python程序及时获得haskell程序的输出。这个管道是单向的——显然不是问题中所要求的——这个警告至少应该在回答中提到。非常感谢。实际上,我刚刚使用子流程模块使其工作。如果有人感兴趣,我可以发布我的问题解决方案,它稍微短一点。不过,您的解决方案看起来也很棒!
-- File "./Hs.hs"

import Control.Concurrent                                                   
import System.IO

main = do
  -- Important
  hSetBuffering stdout NoBuffering

  -- Read a line
  line <- getLine

  -- parse the line and add one and print it back
  putStrLn (show (read line + 1))

  -- Emphasize the importance of hSetBuffering :P
  threadDelay 10000000
# File "./pyrun.py"

import os                                                                   
here = os.path.dirname(os.path.abspath(__file__))

from twisted.internet import tksupport, reactor, protocol
from twisted.protocols.basic import LineReceiver

from Tkinter import Tk, Label, Entry, StringVar

# Protocol to handle the actual communication
class HsProtocol(protocol.ProcessProtocol):
    def __init__(self, text):
        self.text = text

    def connectionMade(self):
        # When haskell prog is opened
        towrite = self.text + '\n'

        # Write a line to the haskell side
        self.transport.write(towrite)

    def outReceived(self, data):
        # When haskell prog write something to the stdout
        # Change the label in the tk window to be the received data
        label_var.set(data[:-1])

def send_num_to_hs(_event):
    content = enternum.get()

    # The abspath of the haskell program
    prog = os.path.join(here, 'Hs')
    reactor.spawnProcess(HsProtocol(content), # communication protocol to use                                           
                         prog, # path
                         [prog] # args to the prog
                         )

# Setting up tk
root = Tk()

# On main window close, stop the tk reactor
root.protocol('WM_DELETE_WINDOW', reactor.stop)

# Since I'm going to change that label..
label_var = StringVar(root, 'Enter a number')

# Label whose content will be changed
label = Label(root, textvariable=label_var)
label.pack()

# Input box
enternum = Entry(root)
enternum.pack()
enternum.bind('<Return>', send_num_to_hs)

# Patch the twisted reactor
tksupport.install(root)

# Start tk's (and twisted's) mainloop
reactor.run()