[Tutor] Simple Python Telnet Client (Help with Asynchronous IO)

2010-08-03 Thread Nathan Farrar
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?

2010-08-03 Thread Richard D. Moores
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

2010-08-03 Thread Peter Otten
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?

2010-08-03 Thread Steven D'Aprano
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

2010-08-03 Thread Alex Baraibar
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.

2010-08-03 Thread Wesley Brooks
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.

2010-08-03 Thread Peter Otten
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.

2010-08-03 Thread Wesley Brooks
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.

2010-08-03 Thread Wesley Brooks
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

2010-08-03 Thread Mac Ryan
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