I had the same problem, I think, and I hope this information will help. In my case, I am connecting to the mel and python ports in Maya, so I have no idea if this experience will be useful to you and your situation.
This answer showed me that I didn't need Telnet/telnetlib at all for the I/O I was trying to do, and recommended asynchat.
It turned out not all output that appeared on the server side was available for the client to read. I had no idea that was a thing that could happen until I used asynchat as a second opinion and saw I still wasn't receiving the output from "print 'Complete Command'" no matter how I sent it. (I was trying to write "print 'Complete Command'" and read the result to know when my previous command had completed.)
I ended up calling mel's warning command, which does produce client-readable output. Sending innocent data as a warning is pretty distasteful, but fortunately this is for an internal tool.
- telnetlib doesn't seem to queue writes. Thus my plan to send two commands back to back (the real command, then the "Command Complete" announcement) doesn't always work. Thus it seems like reading telnetlib output is only workable if you know exactly the output you want to read_until(), or you're willing to sleep until you suspect the output is done. However asynchat.push() definitely queues writes as expected.
A sample, to be taken with a huge grain of salt as I'm still figuring this out :
class mayaClient(asynchat.async_chat) :
...
def __init__(self, sock, clientType):
asynchat.async_chat.__init__(self, sock=sock)
self.clientType = clientType
self.ibuffer = []
self.obuffer = ""
self.set_terminator("\r\n")
self.cumulativeResponse = ""
@classmethod
def withSocket(cls, host, clientType, log) :
melSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
portNumber = cls.MEL_PORT_NUMBER if clientType == cls.MEL else cls.PYTHON_PORT_NUMBER
melSocket.connect((host, portNumber))
return cls(melSocket, clientType, log)
#############################################################
# pushAndWait
#############################################################
def pushAndWait(self, command, timeout=60) :
"""
ACTION: Push a command and a "command complete" indicator
If command completed, return number of milliseconds it took
If command timed out without completing, return -1
INPUT: command as string
description (optional) as string for more informative logging
timeout in seconds as int after which to give up
OUTPUT: X milliseconds if command completed
-1 if not
"""
self.found_terminator()
incrementToSleep = .001
self.push("%s\r\n"%command)
responseToSeek = "Command Complete"
self.push('Whatever command is going to create readable output for %s`); \r\n'%responseToSeek)
timeSlept = 0
while responseToSeek not in self.currentBufferString() and timeSlept < timeout :
self.read()
timeSlept += incrementToSleep
time.sleep(incrementToSleep)
if responseToSeek in self.currentBufferString() :
return timeSlept
return -1
#############################################################
# read
#############################################################
def read(self) :
"""
ACTION: Reads the current available output
and stores it in buffer
"""
try :
self.collect_incoming_data(self.recv(1024))
except Exception, e :
# Don't worry about it -- just means there's nothing to read
#
pass
#############################################################
# currentBuffer
#############################################################
def currentBuffer(self) :
return self.ibuffer
#############################################################
# currentBufferString
#############################################################
def currentBufferString(self) :
return "".join(self.ibuffer)
#############################################################
# collect_incoming_data
#############################################################
def collect_incoming_data(self, data):
"""Buffer the data"""
self.ibuffer.append(data)
#############################################################
# found_terminator
#############################################################
def found_terminator(self):
print "Clearing --%s...-- from buffer"%self.currentBufferString()[0:20]
self.ibuffer = []