[squeak-dev] reading and writing from STDIN and STDOUT

Jason Rogers jacaetevha at gmail.com
Fri May 15 06:21:31 UTC 2009


On Fri, May 15, 2009 at 1:31 AM, Jason Rogers <jacaetevha at gmail.com> wrote:
> On Tue, May 12, 2009 at 8:59 PM, David T. Lewis <lewis at mail.msen.com> wrote:
>> On Tue, May 12, 2009 at 04:59:27PM -0400, Jason Rogers wrote:
>>> I am competing in a friendly Code Smackdown at work.  Smalltalk vs.
>>> All on-comers (Haskell, Erlang, LISP, Java, C and Python).  The
>>> challenge is to write a client for a Chinese Poker game.
>>>
>>> Everything is going well except communicating with the Python-based
>>> server.  I am having trouble reading and writing from STDIN and
>>> STDOUT.  I've installed OSProcess which should give me access to these
>>> streams, but I don't see how to read one line at a time from STDIN and
>>> then get a handle on STDOUT to write a line.  Anyone have pointers or
>>> sample code?
>>>
>>> Also, the image needs to be launched by Python with code like...
>>>
>>>    subprocess.Popen(["/Application/Squeak/Contents/MacOS/Squeak VM
>>> Opt", "/Users/jrogers/Squeak/images/chinese_poker.image", "Squeak
>>> Client"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>>
>>> This will obviously need to change for a server running on another OS.
>>>  The question I have here is how to start a process reading from STDIN
>>> as soon as the VM is fired up.  Should I just create an object that is
>>> waiting on STDIN, reading a line at a time, before saving the image?
>>> That way it would just keep trying to read when the image was fired up
>>> again.
>>
>> Hi Jason,
>>
>> I'm assuming that you are using OS X or other unix based OS (note
>> that OSProcess does not do pipes correctly on Windows, so you won't
>> be able to do that).
>>
>> Please install CommandShell in addition to OSProcess, as that will give
>> you better ways to control external processes connected by pipes. I'm
>> not clear from your question as to whether Python or Squeak is the
>> "client" in this scenario, but it sounds like you will want to have
>> Squeak making requests to a Python server, but you want Python to
>> set up the pipes and invoke Squeak as a subprocess. I don't have
>> an example of this scenario exactly, but the following may help.
>>
>> For an example of Squeak as the client, but where Squeak (not Python)
>> does all the work of setting up the pipes connections to the server,
>> see PipeableOSProcess class>>tkExample. This shows Squeak running
>> a tk/tcl interpreter and putting up a trivial UI with buttons connected
>> to Squeak.
>>
>> For an example of Squeak as the server, communicating through its
>> STDIN and STDOUT streams (which might be pipes set up by Python in
>> your scenario), see class ExternalCommandShell. After evaluating
>> "ExternalCommandShell start" your Squeak image will read command
>> lines from STDIN and respond on STDOUT. The ExternalCommandShell
>> will evaluate input commands and Smalltalk expressions, returning
>> its output to the STDOUT stream. This does not sound like what you
>> want for your project, but it should give you an idea of how these
>> things can be done.
>>
>> In general, the STDIN steam is "OSProcess thisOSProcess stdIn" and
>> the STDOUT and STDERR streams are "OSProcess thisOSProcess stdOut"
>> and "OSProcess thisOSProcess stdErr". Do not save these in variables,
>> but evaluate them at runtime so your Squeak image can find the right
>> input/output streams even after an image restart. That means you can
>> start a Process in Squeak that reads from stdIn and writes to stdOut.
>> Leave the process running when you save the image, and it will carry
>> on where it left off whenever your Python program restarts the Squeak
>> image.
>>
>> Note that the stdIn stream for Squeak is (and must be) non-blocking in
>> order to prevent locking up the Squeak VM on a blocked read. That means
>> that your process will need to read available data from stdIn, possibly
>> looping until you get a complete string of whatever you are looking for.
>> For example, if ten characters are currently available in your STDIN
>> input stream, then "OSProcess thisOSProcess stdIn next: 10000" will
>> answer a string of length ten.
>>
>> ExternalCommandShell does this all in an event-driven manner with
>> no polling, so you can copy that if you want to get fancy. Otherwise
>> a simple polling loop in your process will probably work well enough.
>> Put a 100 ms delay in whatever loop is reading from stdIn an you will
>> get tolerable performance.
>>
>> Dave
>
> Thanks again Dave for the help.  My tack was to "copy"
> ExternalCommandShell's pattern.  StdIn is working fine, but when I
> write to StdOut nothing seems to actually "get out".  Any ideas?
>
> I'm running on Mac, I don't have the AioPlugin installed (I've
> commented out the inform: that tells about the plugin not being there
> and therefore polling will be used).  I'm not verbose enough at
> building plugins.
>
> Any ideas why?  I can post my Monticello file(s) somewhere if that would help.

I hate to respond to my own post, but the problem was not in the
Smalltalk code, it was in the Python server that spawned the image.
It was looking for a line feed in the stdout stream.

-- 
Jason Rogers

"I am crucified with Christ: nevertheless I live;
yet not I, but Christ liveth in me: and the life
which I now live in the flesh I live by the faith of
the Son of God, who loved me, and gave
himself for me."
    Galatians 2:20



More information about the Squeak-dev mailing list