当前位置: 动力学知识库 > 问答 > 编程问答 >

user interface - Connecting A Haskell Program to a Python Program via Pipelines (in Python)

问题描述:

Bear with me as I'm fairly new to programming. My basic question is this. I have a program written in Haskell whose stdout I want to connect to the stdin of a Python program (which will manage the GUI related stuff). Similarly, I want to connect the stdout of the Python program to the stdin of the Haskell program so that it can send information about what the user clicked/typed in to the Haskell program.

The first question is this, if I set up a pipeline between the two, assuming the stdout of the Python program is hooked up to the Haskell program, if I use Tkinter to create widgets and stuff, will they be displayed on the screen nonetheless?

The second question is how exactly would I establish this pipeline? Consider the following example code..

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

The Python code would look something like this.

from Tkinter import *

root = Tk()

label = Label(root, text = "Enter a number.")

label.pack()

enternum = Entry(root)

enternum.pack()

enternum.bind("<Return>", print_num)

-- print_num would essentially be a function to send the Haskell program the number

-- which would be received by the getLine function the way I have it.

I'm sorry if this has already been asked before, but thanks for helping me out!

网友答案:

I did it using Twisted since it provides great abstraction over polling. Basically you need to first define the ways (called protocol in Twisted) how Python and Haskell programs communicate with each other, E.g., how long a data packet is, how to handle errors etc. Then you just code them up.

Here is the haskell code:

-- 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

And here is the Python code:

# 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()                                                                                                           
网友答案:

You can also establish the pipeline from a command shell:

mypython.py | myhaskell.hs

The Haskell program will respond the same as it would to any other type of standard input, as in:

myhaskell.hs

分享给朋友:
您可能感兴趣的文章:
随机阅读: