<HTML>
<HEAD>
<TITLE>Re: [Twisted-Python] Newbie question: can't get getProcessOutput to run from inside a listenTCP service call-back</TITLE>
</HEAD>
<BODY>
<FONT FACE="Calibri, Verdana, Helvetica, Arial"><SPAN STYLE='font-size:14pt'>Hi Nick;<BR>
<BR>
Thanks for the answer. However, If I take the while loop out, &nbsp;&#8220;helloWorldTest()&#8221; returns immediately, and the Flex app gets the initial value of self.result. The defer.callback function doLog never gets called. &nbsp;If I call &nbsp;the &#8220;terminate()&#8221; from the Flex app, which in turn calls reactor.sop() &nbsp;the doLog &nbsp;function finally then gets called. &nbsp;&nbsp;I am looking for what I need to do to allow getProcessOutput to run such that the defer.callback function doLog actually gets called. <BR>
<BR>
I have figured out that if instead of calling getProcessOutput() directly within the helloWorldTest() method, that I can queue it for running &nbsp;after helloWorldTest() as returned, as in:<BR>
&nbsp;&nbsp;&nbsp;&nbsp;reactor.callLater(1, self. helloWorldTest2)<BR>
&nbsp;and that the defer.callback function doLog does then get called.<BR>
<BR>
This means that the defer.callback function doLog will get &nbsp;called after the helloWorldTest() &nbsp;has returned. I see can call helloWorldTest() , and then keep querying the python service from the Flex app until the &nbsp;defer.callback function doLog &nbsp;has run. &nbsp;<BR>
<BR>
I still don&#8217;t understand why calling getProcessOutput() directly within the helloWorldTest() method doesn&#8217;t work. Any explanation would be welcome.<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;Thanks, &nbsp;Read Roberts<BR>
<BR>
On 10/17/09 1:53 AM, &quot;Nick Joyce&quot; &lt;<a href="nick@boxdesign.co.uk">nick@boxdesign.co.uk</a>&gt; wrote:<BR>
<BR>
</SPAN></FONT><BLOCKQUOTE><FONT FACE="Calibri, Verdana, Helvetica, Arial"><SPAN STYLE='font-size:14pt'>On 17 Oct 2009, at 05:15, Read Roberts wrote:<BR>
<BR>
&gt; I have a Python server using twisted which responds to pyAMF calls <BR>
&gt; from<BR>
&gt; Flex/Air applications (following Bruce Eckels 5/1/2008 article <BR>
&gt; &quot;Concurrency<BR>
&gt; with Python, Twisted, and Flex&quot;). The service is basically as <BR>
&gt; follows below.<BR>
&gt; When the client calls a service API, the API needs to make a OS <BR>
&gt; shell call.<BR>
&gt; I see that if I call reactor.stop() after the &nbsp;getProcessOutput call <BR>
&gt; (such<BR>
&gt; as within the doLog and doError functions), the call happens and I <BR>
&gt; see the<BR>
&gt; output. How can can I retrieve the output without calling <BR>
&gt; reactor.stop()? In<BR>
&gt; the example below, the AIR app calls the callback helloWorldTest(), <BR>
&gt; and the<BR>
&gt; deferred.addCallback function is never called.<BR>
&gt;<BR>
&gt; import os<BR>
&gt; from twisted.spread import pb<BR>
&gt; from &nbsp;twisted.internet.utils import getProcessOutput<BR>
&gt; from twisted.internet import reactor<BR>
&gt;<BR>
&gt; class FlexInterface(pb.Root):<BR>
&gt; &nbsp;&nbsp;&nbsp;def __init__(self):<BR>
&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.result e<BR>
&gt;<BR>
&gt; &nbsp;&nbsp;&nbsp;def doLog(self, result):<BR>
&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.result = &quot;%s&quot; % (result)<BR>
&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return result<BR>
&gt;<BR>
&gt; &nbsp;&nbsp;&nbsp;def doError(self, failure):<BR>
&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.result = &quot;%s&quot; % ( failure)<BR>
&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return failure<BR>
&gt;<BR>
&gt; &nbsp;&nbsp;&nbsp;def helloWorldTest(self):<BR>
&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;deferred = getProcessOutput(&quot;echo&quot;, [&quot;Hello World&quot;], <BR>
&gt; os.environ)<BR>
&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;deferred.addErrback(self.doError)<BR>
&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;deferred.addCallback(self.doLog)<BR>
&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while (self.result == None)<BR>
&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;doLog still hasn't been called&quot;<BR>
&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return self.result<BR>
<BR>
<BR>
The while loop will block the event loop, preventing the deferred from <BR>
ever being called. PyAMF will accept a deferred as a return value for <BR>
the service function and will not return a response until the <BR>
deferred's callback is fired.<BR>
<BR>
So, you could re-write the method like:<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def helloWorldTest(self):<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;deferred = getProcessOutput(&quot;echo&quot;, [&quot;Hello World&quot;], <BR>
os.environ)<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;deferred.addErrback(self.doError)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;deferred.addCallback(self.doLog)<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return deferred<BR>
<BR>
If the deferred's callback is called then the return value of doLog <BR>
will be used as the response value. If the errback is called, the <BR>
return value of doError will be used as the response, in this case a <BR>
Failure instance. PyAMF converts Failure instances to remoting/<BR>
messaging error objects automagically, so the faultHandler on the <BR>
flash/air side will be called.<BR>
<BR>
hth,<BR>
<BR>
Nick<BR>
<BR>
<BR>
_______________________________________________<BR>
Twisted-Python mailing list<BR>
<a href="Twisted-Python@twistedmatrix.com">Twisted-Python@twistedmatrix.com</a><BR>
<a href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python">http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python</a><BR>
<BR>
</SPAN></FONT></BLOCKQUOTE>
</BODY>
</HTML>