The code is in attachment.

I run it on Debian/Linux, twisted 10.0.0
When you run it on a terminal, it works by prefixing the data you enter with 
"dataReceived: "
and outputting that back to terminal.
 $ ./program.py
i: blabla
o: dataReceived: 'blabla
o: '
i: ^D
o: readConnectionLost(input is done)
i: ^C
o: OK
 $

The same happens if you redirect output to a pipe (no matter if it a named FIFO 
or an anonymous pipe).
But if you redirect output to a file or to a /dev/null, this happens:
 $ ./program.py > /dev/null
<a short pause, no input>
o: StdioProtocol.connectionLost('[Failure instance: Traceback (failure with no 
frames): <class 'twisted.internet.error.ConnectionLost'>: Connection to the 
other side was lost in a non-clean fashion.
o: ]')OK
 $

But I expected it to work the same way, regardless of redirections.
I haven't traced the source of that Failure, so just asking, whether that 
behavior is
known, or maybe intended?
Or, perhaps, I do something incorrectly?

Well, right now I'm using the workaround with /bin/cat:
 $ ./program.py > >(cat > file)
or with an extra shell process:
 $ ./program.py | cat > file

#!/usr/bin/python

from twisted.internet.stdio import StandardIO
from twisted.internet.interfaces import IHalfCloseableProtocol
from twisted.internet import protocol, reactor
from zope.interface import implements
import sys

class StdioProtocol(protocol.Protocol):
    implements(IHalfCloseableProtocol)

    def __init__(self):
        pass

    # IBaseProtocol
    def connectionMade(self):
        pass

    # IProtocol
    def dataReceived(self, data):
        sys.stderr.write("dataReceived: '%s'\n" %(data))

    def connectionLost(self, reason):
        # some error happened to stdio, like exception in my code
        from twisted.internet.error import ConnectionDone
        if isinstance(reason.value, ConnectionDone):
            sys.stderr.write("ConnectionDone (clean)\n")
        else:
            sys.stderr.write("StdioProtocol.connectionLost('%s')" % (reason))
        reactor.callLater(0, reactor.stop)

    # IHalfCloseableProtocol
    def writeConnectionLost(self, reason=SystemExit("output pipe is broken")):
        # no more writing is possible, pipe is broken, output is closed
        # This is the end.
        sys.stderr.write("writeConnectionLost(%s)" %(reason))
        self.transport.loseConnection()

    def readConnectionLost(self, reason=EOFError("input is done")):
        # EOF on stdin, congratulations, no more tasks will arrive!
        sys.stderr.write("\nreadConnectionLost(%s)\n\n" %(reason))

p = StdioProtocol()
t = StandardIO(p)

reactor.run()
sys.stderr.write("OK\n")
_______________________________________________
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

Reply via email to