[Tutor] Simple Python Telnet Client (Help with Asynchronous IO)
Hello All, I'm attempting to write a simple telnet client. Yes, I've been told that I should be using twisted to do this. I want to learn to do it myself first, so that I can fully understand the concepts - then I will scrap it and switch to using twisted. When I started, I didn't realize there was such a thing as blocking IO. I assumed that if I put the read/write calls for stdio & the socket in different threads all would be good. I've been told that this is not the case and that if I perform a blocking IO call in a thread (such as sys.stdin.read()) it will halt the execution of all threads in the process. I found an example that uses the select module to see if any data is available from stdin before attempting to read ... and that this is the asynchronous/non-blocking way to do it. I've implemented this code, but I can't figure out a similar way to do this with the socket. Here's the code I've put together so far: #!/usr/bin/env python import collections import os import select import socket import sys import termios import tty import threading class InputThread(threading.Thread): """ Read data from the stdin and place in the input buffer. """ def __init__(self, input_buffer): threading.Thread.__init__(self) self.input_buffer = input_buffer def run(self): self.old_settings = termios.tcgetattr(sys.stdin) tty.setcbreak(sys.stdin.fileno()) # prompt loop try: while True: if select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []): self.input_buffer.append(sys.stdin.read()) print "> " finally: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self.old_settings) class DisplayThread(threading.Thread): """ Check ouput buffer for data. Print and data and flush buffer. """ def __init__(self, output_buffer): threading.Thread.__init__(self) self.output_buffer = output_buffer def run(self): while True: while len(self.output_buffer) > 0: output_data = self.output_buffer.pop() print output_data, class SocketThread(threading.Thread): """ Check input buffer. If data exists, send it to socket. Read any incoming data from socket and place it in output buffer. """ def __init__(self, input_buffer, output_buffer): threading.Thread.__init__(self) self.input_buffer = input_buffer self.output_buffer = output_buffer def run(self): self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.setblocking(1) self.socket.connect(('nannymud.lysator.liu.se',2000)) while True: while len(self.input_buffer) > 0: input_data = self.input_buffer.pop() self.socket.send(input_data, '\n') self.output_buffer.append(self.socket.recv(1024)) self.sock.close() def main(): """ Interactive, multithreaded network client written in python. """ print "Use 'quit' to exit client." input_buffer = collections.deque() output_buffer = collections.deque(); input_thread = InputThread(input_buffer) input_thread.start() display_thread = DisplayThread(output_buffer) display_thread.start() socket_thread = SocketThread(input_buffer, output_buffer) socket_thread.start() if __name__ == '__main__': main() Help sorting this out so that I can fully understand the concepts and get this working would be greatly appreciated. As I mentioned previously, I am fully planning on scrapping this and rewriting it using twisted once I understand the concepts and have a working prototype. Thank you! - F4RR4R -- Science replaces private prejudice with publicly verifiable evidence. - Richard Dawkins ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] How to get script to detect whether a file exists?
On Tue, Aug 3, 2010 at 08:04, Steven D'Aprano wrote: > On Tue, 3 Aug 2010 10:52:27 am Richard D. Moores wrote: >> On Mon, Aug 2, 2010 at 16:57, Steven D'Aprano > wrote: >> > # File *probably* doesn't exist. Consider better error checking. >> >> Steve, before I dig into your detailed reply, please tell me what you >> meant by " # File *probably* doesn't exist. Consider better error >> checking.". > > open(pathname) will fail with an IOError for many reasons. It could be > that the file simply doesn't exist, so it can't be opened. It could be > that you don't have read permission, or that the disk is corrupt and > even though you have permission to open the file, attempting to do so > fails. > > For a simple script, it's acceptable to assume that the likely reason > for IOError is that the file isn't there, and therefore creating it > will solve the problem. But for a more solid program, you should > inspect the exception to determine the error code, and then take > appropriate action. Ah. Got it. Thanks, Steven. Dick ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Conflict with encoding in console view and file dump
Alex Baraibar wrote: > Hi, Peter. > Sorry for the delay, I've been out for a while. > So I did what you suggested and it prints the following: > > " > import sys > print >> sys.stderr, sys.stdout.encoding > > what does the above print > (a) when you print to the console? it prints cp850 > (b) when you redirect to a file? it prints None That's as expected. You should normally get an exception like Traceback (most recent call last): File "tmp_enc.py", line 33, in print element UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 11: ordinal not in range(128) when you redirect your script's output to a file. Did you change the default encoding? If you didn't you probably have an ill- behaved application on your system that did it without asking. > Any suggestions? Check stdout.encoding, and if it is None (unknown encoding) wrap the stdout stream into a Writer. Your script with that modification: # -*- coding: cp1252 -*- def festivos(): fest = [ 'Any Nou:\t\t\t1 de enero', 'Reis:\t\t\t\t6 de enero', 'Festa del Treball:\t\t1 de mayo', 'Sant Joan:\t\t\t24 de junio', u'La Assumpció:\t\t\t15 de agosto', 'La Diada:\t\t\t11 de septiembre', u'La Mercè:\t\t\t24 de septiembre', 'La Hispanitat:\t\t\t12 de octubre', 'Tots Sants:\t\t\t1 de novembre', u'La Constitució:\t\t\t6 de desembre', u'La Concepció:\t\t\t8 de desembre', 'Nadal:\t\t\t\t25 de desembre', 'Sant Esteve:\t\t\t26 de desembre' ] return fest def separador( num, char ): return char * num # --- Main --- import sys if sys.stdout.encoding is None: import codecs Writer = codecs.getwriter("latin-1") sys.stdout = Writer(sys.stdout) dias = festivos() print "Los festivos fijos anuales son:\n" for element in dias: sep = separador( 50, '-' ) # move that out of the loop print element print sep Peter ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] How to get script to detect whether a file exists?
On Tue, 3 Aug 2010 10:52:27 am Richard D. Moores wrote: > On Mon, Aug 2, 2010 at 16:57, Steven D'Aprano wrote: > > # File *probably* doesn't exist. Consider better error checking. > > Steve, before I dig into your detailed reply, please tell me what you > meant by " # File *probably* doesn't exist. Consider better error > checking.". open(pathname) will fail with an IOError for many reasons. It could be that the file simply doesn't exist, so it can't be opened. It could be that you don't have read permission, or that the disk is corrupt and even though you have permission to open the file, attempting to do so fails. For a simple script, it's acceptable to assume that the likely reason for IOError is that the file isn't there, and therefore creating it will solve the problem. But for a more solid program, you should inspect the exception to determine the error code, and then take appropriate action. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Conflict with encoding in console view and file dump
Hi, Peter. Sorry for the delay, I've been out for a while. So I did what you suggested and it prints the following: " import sys print >> sys.stderr, sys.stdout.encoding what does the above print (a) when you print to the console? it prints cp850 (b) when you redirect to a file? it prints None " Any suggestions? Thanx for your time. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Maximum recursion depth problem.
Morning Peter, Thanks, that was something I was unaware of! Not sure how I hadn't bumped into that before! Cheers, Wesley. On 3 August 2010 11:40, Peter Otten <__pete...@web.de> wrote: > Wesley Brooks wrote: > >> I'm having real difficulty understanding why the following is not >> working and hoped I've either missed something obvious of I'm doing >> something wrong! >> >> class A: >> def break_down(self, value, base, broken_list=[]): > >> I'm a little stumped as I don't think I'm using any global or class >> variables? Any help would be much appreciated. > > You are on the right track, the default value for broken_list is > evaluated only once; Modifications during an invocation of the > break_down() method are visible when break_down() is called again later. > > See also > > http://docs.python.org/faq/design.html#why-are-default-values-shared-between-objects > > Peter > > > ___ > Tutor maillist - tu...@python.org > To unsubscribe or change subscription options: > http://mail.python.org/mailman/listinfo/tutor > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Maximum recursion depth problem.
Wesley Brooks wrote: > I'm having real difficulty understanding why the following is not > working and hoped I've either missed something obvious of I'm doing > something wrong! > > class A: > def break_down(self, value, base, broken_list=[]): > I'm a little stumped as I don't think I'm using any global or class > variables? Any help would be much appreciated. You are on the right track, the default value for broken_list is evaluated only once; Modifications during an invocation of the break_down() method are visible when break_down() is called again later. See also http://docs.python.org/faq/design.html#why-are-default-values-shared-between-objects Peter ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Maximum recursion depth problem.
Ok a little more investigation has found the follwing work but there not as tidy. I'd still really appreciate someone explaing why this behaves like this! class A: def break_down(self, value, base, broken_list=[]): power = len(broken_list) digit = (value % (base ** (power + 1))) / (base ** power) value -= digit * (base**power) broken_list.append(digit) if value != 0: return self.break_down(value, base, broken_list=broken_list) else: return broken_list if __name__ == '__main__': a = A() d_list_1 = a.break_down(34567, 256, []) print d_list_1 a2 = A() d_list_2 = a2.break_down(34567, 256, []) print d_list_2 ..OR: class A: def break_down(self, value, base, broken_list=None): if broken_list == None: broken_list = [] power = len(broken_list) digit = (value % (base ** (power + 1))) / (base ** power) value -= digit * (base**power) broken_list.append(digit) if value != 0: return self.break_down(value, base, broken_list=broken_list) else: return broken_list if __name__ == '__main__': a = A() d_list_1 = a.break_down(34567, 256) print d_list_1 a2 = A() d_list_2 = a2.break_down(34567, 256) print d_list_2 Yours Faithfully, Wesley Brooks On 3 August 2010 11:02, Wesley Brooks wrote: > Dear Python Users, > > I'm having real difficulty understanding why the following is not > working and hoped I've either missed something obvious of I'm doing > something wrong! > > class A: > def break_down(self, value, base, broken_list=[]): > power = len(broken_list) > digit = int((value % (base ** (power + 1))) / (base ** power)) > value -= digit * (base**power) > broken_list.append(digit) > if value != 0: > return self.break_down(value, base, broken_list=broken_list) > else: > return broken_list[:] > > if __name__ == '__main__': > a = A() > d_list_1 = a.break_down(34567, 256) > print d_list_1 > a2 = A() > d_list_2 = a2.break_down(34567, 256) > print d_list_2 > > When the above runs it fails with the error "RuntimeError: maximum > recursion depth exceeded while calling a Python object". > > The following also does not work: > > if __name__ == '__main__': > a = A() > digit_list_1 = a.break_down(34567, 256) > print digit_list_1 > del digit_list_1, usc > a2 = A() > digit_list_2 = a2.break_down(34567, 256) > print digit_list_2 > > but the following two do work: > > if __name__ == '__main__': > a = A() > digit_list_1 = a.break_down(34567, 256) > print digit_list_1 > #a2 = A() > #digit_list_2 = a2.break_down(34567, 256) > #print digit_list_2 > > if __name__ == '__main__': > #a = A() > #digit_list_1 = a.break_down(34567, 256) > #print digit_list_1 > a2 = A() > digit_list_2 = a2.break_down(34567, 256) > print digit_list_2 > > I'm a little stumped as I don't think I'm using any global or class > variables? Any help would be much appreciated. > > Yours Faithfully, > > Wesley Brooks > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
[Tutor] Maximum recursion depth problem.
Dear Python Users, I'm having real difficulty understanding why the following is not working and hoped I've either missed something obvious of I'm doing something wrong! class A: def break_down(self, value, base, broken_list=[]): power = len(broken_list) digit = int((value % (base ** (power + 1))) / (base ** power)) value -= digit * (base**power) broken_list.append(digit) if value != 0: return self.break_down(value, base, broken_list=broken_list) else: return broken_list[:] if __name__ == '__main__': a = A() d_list_1 = a.break_down(34567, 256) print d_list_1 a2 = A() d_list_2 = a2.break_down(34567, 256) print d_list_2 When the above runs it fails with the error "RuntimeError: maximum recursion depth exceeded while calling a Python object". The following also does not work: if __name__ == '__main__': a = A() digit_list_1 = a.break_down(34567, 256) print digit_list_1 del digit_list_1, usc a2 = A() digit_list_2 = a2.break_down(34567, 256) print digit_list_2 but the following two do work: if __name__ == '__main__': a = A() digit_list_1 = a.break_down(34567, 256) print digit_list_1 #a2 = A() #digit_list_2 = a2.break_down(34567, 256) #print digit_list_2 if __name__ == '__main__': #a = A() #digit_list_1 = a.break_down(34567, 256) #print digit_list_1 a2 = A() digit_list_2 = a2.break_down(34567, 256) print digit_list_2 I'm a little stumped as I don't think I'm using any global or class variables? Any help would be much appreciated. Yours Faithfully, Wesley Brooks ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Where to start with Unit Testing
On Mon, 2010-08-02 at 11:59 -0400, Che M wrote: > Mac, I found this an excellent brief overview of UT and your points > all > seem very strong to me. Thanks very much. I admit I didn't really > know > anything about the topic and was mentioning my feelings on the matter > partly to elicit enlightening responses like this (maybe because I was > feeling > like I was being irresponsible with my own project by not learning UT > and running tests). > > I am in the "hobbyist programmer busy on a simple one-off small app" > camp ("simple" is relative...though it is clearly nothing like a big > e-commerce application!), so I feel OK with foregoing getting into UT > for now. If things get more complex and I at some point have actual > users > instead of the large number of vapor users I have now (:D) I may > buckle > down and learn it. No worries than, I am happy my answer was of some use. Unit testing in python is however very very easy to use in a great number of situations, so don't be scared to get your hands dirty with it! A few days back I read this sentence: "Later than you expected, but sooner than you think" which in the context meant that we tend to over-estimate our abilities prior to start something new, but than - once we started working on it, we contrarily under-estimate our ability to achieve quickly a good level of performance... Happy learning! :) Mac. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor