Re: [Tutor] sending email via smtplib

2012-11-19 Thread Saad Javed
Using port 25 with SMTP_SSL gives:

Traceback (most recent call last):
  File "sendemail.py", line 22, in 
smtp = smtplib.SMTP_SSL(smtp_srv, 25)
  File "/usr/lib/python2.7/smtplib.py", line 776, in __init__
SMTP.__init__(self, host, port, local_hostname, timeout)
  File "/usr/lib/python2.7/smtplib.py", line 249, in __init__
(code, msg) = self.connect(host, port)
  File "/usr/lib/python2.7/smtplib.py", line 309, in connect
self.sock = self._get_socket(host, port, self.timeout)
  File "/usr/lib/python2.7/smtplib.py", line 782, in _get_socket
new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile)
  File "/usr/lib/python2.7/ssl.py", line 381, in wrap_socket
ciphers=ciphers)
  File "/usr/lib/python2.7/ssl.py", line 143, in __init__
self.do_handshake()
  File "/usr/lib/python2.7/ssl.py", line 305, in do_handshake
self._sslobj.do_handshake()
socket.error: [Errno 104] Connection reset by peer
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] How to load python code only after program startup?

2012-11-19 Thread Pete O'Connell
Hi I use a compositing program called Nuke which loads my custom modules on
start up. So if I have an error in my python code somewhere, Nuke won't
open and it throws a typical error which is easy enough to fix.
The problem I am running into is that when others on my network are using
an older version of Nuke, some of my code causes their older version to not
open. For example, recently I started using gnuplot.py for graphical feed
back which the older version of Nuke doesn't like.
So my question is:
What is the best way to wrap all my custom code so that it isn't read on
startup, but rather only after I invoke a "loadMyCustomModules.py" module.

Help please:)!

Pete
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] New to Python - simple question

2012-11-19 Thread Oscar Benjamin
On 18 November 2012 14:07, Unaiza Ahsan  wrote:
> Hi all,
>
>
> The function histogram is supposed to come from the numpy module; at
>
> least that's the case on my computer (I have numpy 1.6.2 for Python
> 2.7):
>
 from numpy import *
>
 histogram
> 
>
> Maybe something is wrong with Unaiza's version of numpy.
>
>
> Kal
>
> Yes it's supposed to come from numpy. In imtools.py, the following line is
> there:
> from numpy import *
>
> But I'm still getting the error. Since I'm a beginner in Python, I'm not at
> all sure what's wrong here.

I've checked and I also have a histogram function in my numpy module
so I don't understand what the problem is.

What would make it possible for us to help you, Unaiza, is if you
provide a short piece of code that demonstrates the problem you are
having. Perhaps you could just post the whole of the code you are
using but if you are able to shorten it while still demonstrating the
problem then that is better.

Reading the link below will help you to seek help from others. In
particular I don't have enough information to check if your code would
work on my computer or not, so it's difficult for me to help you right
now:
http://sscce.org/

The ideal thing would be if you could make a single Python script that
shows the problem you are having. If that is not possible then please
provide complete code and also as much as possible information about
how you are running your script, what folder it's in and what other
modules are in the folder and so on (more information is usually
better).


Oscar
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help

2012-11-19 Thread Steven D'Aprano

On 20/11/12 11:33, Mark Lawrence wrote:

On 19/11/2012 23:28, Matthew Ngaha wrote:

It's asking a lot if you want people to read your whole code to try
and spot the errors. Try to run it from the console and paste what the
errors are here.


I believe that to be complete nonsense, there was very little code to
parse. What was missing I've already asked for in a separate reply.


My, you're argumentative today :)

You *also* asked the Original Poster to explain what errors he got. Your
exact words:

"Stating there are some errors is as useful as a chocolate teapot. ...
What are you expecting to happen, WHAT ACTUALLY HAPPENED?"
[emphasis added]

Whether there are 1 lines or 10 lines, telling people "there are errors"
and expecting them to work out for themselves what those errors are *is*
asking a lot. We're volunteers here, people asking for help are asking us
to donate our time for free. Asking us to help identify and fix errors is
one thing. Asking us to *find* the errors first is too much.

Honestly, sometimes I don't understand people on the Internet. No offense to
the original poster Isaac, but do they think that the world resolves around
them and that we're sitting here just dying for the opportunity to be their
unpaid personal servant? If you ask a friend to help you move, you tell him
where you are moving from, you don't say "I'm in the phone book, look me up,
I'm too lazy to tell you my address."

Well, when asking *total strangers* to debug your code, you tell them what
errors you are getting, you don't expect them to work it out for themselves.


--
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help

2012-11-19 Thread Mark Lawrence

On 19/11/2012 23:28, Matthew Ngaha wrote:

It's asking a lot if you want people to read your whole code to try
  and spot the errors. Try to run it from the console and paste what the
  errors are here.


I believe that to be complete nonsense, there was very little code to 
parse.  What was missing I've already asked for in a separate reply.


--
Cheers.

Mark Lawrence.

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help

2012-11-19 Thread Mark Lawrence

On 19/11/2012 18:07, Isaac Parkes wrote:

First of all giving a meaningful subject helps everybody, how about 
"tkinter problems"?



hi,

I'm quite new to python and have just made a program that makes a GUI but
when i open it it says there are some errors. I can't find any :( if you
find any problems could you tell me ASAP



Stating there are some errors is as useful as a chocolate teapot.  How 
did you try to run the code?  What Python version, your code will need 
changing to run on Python 3.x, what OS?  What are you expecting to 
happen, what actually happened?


--
Cheers.

Mark Lawrence.

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] pyXML i Python2.6

2012-11-19 Thread Mark Lawrence

On 19/11/2012 16:33, Sreenivasulu wrote:

Hi,

Am unable to install pyXML in Ubuntu usig python2.6

Could you please help me

Regards,
Sreenu



What have you tried?  What went wrong?  If you don't give such basic 
data how can we help?


--
Cheers.

Mark Lawrence.

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] help

2012-11-19 Thread Matthew Ngaha
It's asking a lot if you want people to read your whole code to try
 and spot the errors. Try to run it from the console and paste what the
 errors are here.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] pyXML i Python2.6

2012-11-19 Thread Sreenivasulu
Hi,

Am unable to install pyXML in Ubuntu usig python2.6

Could you please help me

Regards,
Sreenu
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] New to Python - simple question

2012-11-19 Thread Unaiza Ahsan
*Hi all,

The function histogram is supposed to come from the numpy module; at* *
least that's the case on my computer (I have numpy 1.6.2 for Python
2.7):

>>> from numpy import ** *
>>> histogram


Maybe something is wrong with Unaiza's version of numpy.* *

Kal

*Yes it's supposed to come from numpy. In imtools.py, the following line is
there:
from numpy import *

But I'm still getting the error. Since I'm a beginner in Python, I'm not at
all sure what's wrong here.

Thanks for the pointers/help.
Unaiza
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] New to Python - simple question

2012-11-19 Thread Unaiza Ahsan
* Where is the histogram() function from? Is it in imtools.py as well?
*
It is a NumPY function.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] help

2012-11-19 Thread Isaac Parkes
hi,

I'm quite new to python and have just made a program that makes a GUI but
when i open it it says there are some errors. I can't find any :( if you
find any problems could you tell me ASAP

# Match finder

from TKinter import *

import random

girls = ['Ellie', 'Maddy', 'Ursula', 'Annie', 'Stella',
 'Kimberely', 'Flora', 'Hannah', 'Bella', 'Ella',
 'Rosa', 'Olivia', 'Liya', 'Emma', 'Irene']

boys = ['Charlie', 'sion', 'Mikey', 'Jem', 'Matthew', 'Ethan', 'Kainan',
'Louis', 'Jack', 'Abel', 'Alex', 'Tom', 'Will', 'James', 'Isaac']


class Application(Frame):
""" GUI application which can reveal your perfect match. """
def __init__(self, master):
""" Initialize the frame. """
Frame.__init__(self, master)
self.grid()
self.create_widgets()

def create_widgets(self):
""" Create button, text, and entry widgets. """
# create instruction label
self.inst_lbl = Label(self, text = "Enter details below to find out
your perfect match")
self.inst_lbl.grid(row = 0, column = 0, columnspan = 2, sticky = W)

# create label for name
self.pw_lbl = Label(self, text = "Name: ")
self.pw_lbl.grid(row = 1, column = 0, sticky = W)

# create entry widget to accept name
self.pw_ent = Entry(self)
self.pw_ent.grid(row = 1, column = 1, sticky = W)

# create variable for single, favorite type of movie
self.favorite = StringVar()

# create boy radio button
Radiobutton(self,
gender = "Boy",
variable = self.favorite,
gender1 = "Boy.",
command = self.update_text
).grid(row = 2, column = 0, sticky = W)

# create girl radio button
Radiobutton(self,
gender = "Girl",
variable = self.favorite,
gender1 = "Girl.",
command = self.update_text
).grid(row = 3, column = 0, sticky = W)

# create submit button
self.submit_bttn = Button(self, text = "Submit", command =
self.reveal)
self.submit_bttn.grid(row = 2, column = 0, sticky = W)

# create text widget to display message
self.secret_txt = Text(self, width = 35, height = 5, wrap = WORD)
self.secret_txt.grid(row = 3, column = 0, columnspan = 2, sticky =
W)


def update_text(self):
""" Display message based on match. """
message = "Your perfect match is: ",

if gender == 'boy':
choice = random.choice(girls)
else:
choice = random.choice(boys)
message += choice

self.secret_txt.delete(0.0, END)
self.secret_txt.insert(0.0, message)

# main
root = Tk()
root.title("Match finder")
root.geometry("250x150")

app = Application(root)

root.mainloop()
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] memoize, lookup, or KIS?

2012-11-19 Thread Prasad, Ramit
Albert-Jan Roskam wrote:
> 
[snip]
> > Also, you should have some way to stop the lookup table from growing 
> > forever.
> > If you are running Python 3.3, you can use functools.lru_cache, which
> > implements a Least Recently Used cache. Once the cache reaches a certain 
> > size,
> > the element which was least recently used is flushed.
> >
> 
> I read about that. Time to upgrade! Wish I could use this in the office!
> 

Why can you not? Even if you are not using Python3.2+ you should be able
to back port it from the Python source. You may need to backport other
features (e.g. OrderedDict) depending on the Python version you use.
http://svn.python.org/projects/python/tags/r32b1/Lib/functools.py

Alternatively, you can use Raymond Hettinger's recipe. At a brief glance,
it looks to be Python 2.x compatible.
http://code.activestate.com/recipes/498245/


~Ramit


This email is confidential and subject to important disclaimers and
conditions including on offers for the purchase or sale of
securities, accuracy and completeness of information, viruses,
confidentiality, legal privilege, and legal entity disclaimers,
available at http://www.jpmorgan.com/pages/disclosures/email.  
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] sending email via smtplib

2012-11-19 Thread Prasad, Ramit
Saad Javed wrote:
> 
> I don't think using SSL works with hotmail. I tried using:
> 
> smtplib.SMTP_SSL("smtp.live.com", 587)

You need to use port 25 not 587. 
http://windows.microsoft.com/en-US/hotmail/send-receive-email-from-mail-client

> smtplib.login(user, passwd)
> ...
> 
> That gave this error:
> 
> Traceback (most recent call last):
>   File "sendemail.py", line 22, in 
>     smtp = smtplib.SMTP_SSL(smtp_srv, 587)
>   File "/usr/lib/python2.7/smtplib.py", line 776, in __init__
>     SMTP.__init__(self, host, port, local_hostname, timeout)
>   File "/usr/lib/python2.7/smtplib.py", line 249, in __init__
>     (code, msg) = self.connect(host, port)
>   File "/usr/lib/python2.7/smtplib.py", line 309, in connect
>     self.sock = self._get_socket(host, port, self.timeout)
>   File "/usr/lib/python2.7/smtplib.py", line 782, in _get_socket
>     new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile)
>   File "/usr/lib/python2.7/ssl.py", line 381, in wrap_socket
>     ciphers=ciphers)
>   File "/usr/lib/python2.7/ssl.py", line 143, in __init__
>     self.do_handshake()
>   File "/usr/lib/python2.7/ssl.py", line 305, in do_handshake
>     self._sslobj.do_handshake()
> ssl.SSLError: [Errno 1] _ssl.c:504: error:140770FC:SSL 
> routines:SSL23_GET_SERVER_HELLO:unknown protocol
> 


~Ramit


This email is confidential and subject to important disclaimers and
conditions including on offers for the purchase or sale of
securities, accuracy and completeness of information, viruses,
confidentiality, legal privilege, and legal entity disclaimers,
available at http://www.jpmorgan.com/pages/disclosures/email.  
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] memoize, lookup, or KIS?

2012-11-19 Thread Albert-Jan Roskam


> Emphasis on "might". Unless you have timed the code with or without a 
> lookup
> table, you're just guessing whether it is an optimization or a 
> pessimization.
> 

See my earlier reply to Oscar's mail. I used cProfile and memoizing was almost 
twice as fast in the fastsest implementation.

> On the other hand, my intuition is that it *will* benefit from memoization,
> so my guess is the same as your guess :)
> 
> 
>>  On the other hand, it might complicate the code too much, so it might
>>  be better to Keep It Simple (KIS). Is the code below a sound approach?
> 
> 
> No. You should separate the cache code from the non-cache code. Decorators
> are ideal for that, but even without decorators you should split the code.
> See below.

Yes, it feels a lot less mentally straining to read the code where memoizing 
and the actual job are separated.

> Also, you should have some way to stop the lookup table from growing forever.
> If you are running Python 3.3, you can use functools.lru_cache, which
> implements a Least Recently Used cache. Once the cache reaches a certain size,
> the element which was least recently used is flushed.
> 

I read about that. Time to upgrade! Wish I could use this in the office!


 
> class Test(object):
> 
>     def __init__(self):
>         self._cache = {}
> 
>     def clear_cache(self):
>         self._cache.clear()
> 
>     def spss2strDate(self, gregorianDate, fmt="%Y-%m-%d", 
> recodeSysmisTo=""):
>         # cached wrapper
>         t = (gregorianDate, fmt, recodeSysmisTo)
>         if t in self._cache:
>             # cache hit
>             return self._cache[t]
>         # otherwise cache miss
>         result = self._calculate_spss2strDate(*t)  # this does the real work
>         if len(self._cache) > 1000:
>             self._cache.popitem()  # discard an arbitrary (key,value) pair
>         self._cache[t] = result
>         return result
> 
>     def _calculate_spss2strDate(self, gregorianDate, fmt, recodeSysmisTo):
>         # uncached version
>         return some_calculation(...)
> 
> 
> You can fill in the details for the uncached version :)
> 
> One good improvement would be to add instrumentation[1] to the cache so you 
> can
> tell whether or not the cache is worthwhile. E.g. record how many times each
> set of arguments are used. If you find that hardly any triple of arguments is
> used multiple times (i.e. nearly every call is unique), then the cache is a
> waste of time.

It would be cool if the memoizer "turned off" itself off if hardly items are 
retrieved from it (ie, the calls are almost always unique).
stop_memoizing = (n_cached_version / float(n_newly_calculated_version)) < 
some_threshold and len(cache) > some_value
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] memoize, lookup, or KIS?

2012-11-19 Thread Albert-Jan Roskam


>Presumably the place where you read about them would have listed some
>example decorators that you can use for memoisation. Here's a quick
>example that works for hashable inputs:
>


Some of these I don't really understand so I am hesitant to use them.


>def memo(func):
>    table = {}
>    def wrapper(inputarg):
>        try:
>            return table[inputarg]
>        except KeyError:
>            table[inputarg] = val = func(inputarg)
>            return val
>    return wrapper
>
>@memo
>def square(x):
>    print('Calling square()')
>    return x ** 2


Nice and conscise! I did some profiling and it is fast, too. But as Steven 
said, I also need to maximize the cache, among other things. I also gotta 
figure out what I'll do with datetime values (probably it's not useful to cache 
these).


# 1M function calls
a--115.837 CPU seconds  # no memoization
b--215.753 CPU seconds  # memodict # 
http://code.activestate.com/recipes/578231-probably-the-fastest-memoization-decorator-in-the-/
c--62.547 CPU seconds   # simple decorator # 
http://code.activestate.com/recipes/577219-minimalistic-memoization/
d--60.771 CPU seconds   # Oscar Benjamin, modified to:
    def memo(func):
    table = {}
    def wrapper(*inputarg):
    try:
    return table[inputarg[0:2]] #
    except KeyError:
    table[inputarg[0:2]] = val = func(*inputarg)
    return val
    return wrapper
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] memoize, lookup, or KIS?

2012-11-19 Thread Oscar Benjamin
On 19 November 2012 11:02, Albert-Jan Roskam  wrote:
> Hi,
>
> I have a function that converts a date value, expressed as the number of
> seconds sinds start of the gregorian calendar, into a human-readable format
> (typically an iso-date). So if a record contains x date values, and a data
> set contains y records, the number of function calls are x * y. Imagine a
> data set with 1M records with dob and enrollment_date in in it: the number
> of function calls is huge (well, 2M).

The number of function calls is one factor that affects whether
memoisation is worthwhile. The more important questions are: How often
do you call the function with the same input values? How expensive is
the function compared with the table lookup?

Memoisation can, for a cheap function, actually slow it down. Before
you do anything like this you need to profile your code and ensure
that the function in question is actually a bottleneck. Otherwise
you're wasting memory and coding time without getting much of a speed
up.

> I was reading about memoize decorators the other day and I realized that
> this function might benefit from memoizing, or a lookup table. On the other
> hand, it might complicate the code too much, so it might be better to Keep
> It Simple (KIS). Is the code below a sound approach? I believe that, in
> effect, it uses a memoization approach (as it is a slowly growing lookup
> table).

This function is using memoisation but why aren't you just using the
memoisation decorators that you read about?

> import datetime
>
> class Test(object):
>
> def __init__(self):
> self.isoDateLookup = {}
> self.lookupCount = 0
>
> def spss2strDate(self, gregorianDate, fmt="%Y-%m-%d",
> recodeSysmisTo=""):
> """ This function converts internal SPSS dates (number of seconds
> since midnight, Oct 14, 1582 (the beginning of the Gregorian
> calendar))
> to a human-readable format """
> MAXLOOKUP = 10**6
> try:
> if not hasattr(self, "gregorianEpoch"):
> self.gregorianEpoch = datetime.datetime(1582, 10, 14, 0, 0,
> 0)
> if fmt == "%Y-%m-%d" and len(self.isoDateLookup) <= MAXLOOKUP:
> try:
> result = self.isoDateLookup[gregorianDate]
> self.lookupCount += 1
> except KeyError:
> theDate = self.gregorianEpoch +
> datetime.timedelta(seconds=gregorianDate)
> result = datetime.datetime.strftime(theDate, fmt)
> self.isoDateLookup[gregorianDate] = result
> return result
> else:
> theDate = self.gregorianEpoch +
> datetime.timedelta(seconds=gregorianDate)
> return datetime.datetime.strftime(theDate, fmt)
> except OverflowError:
> return recodeSysmisTo
> except TypeError:
> return recodeSysmisTo
> except ValueError:
> return recodeSysmisTo

The advantage of using a decorator for this are that you don't need to
complicate the internal code of the function that is memoised and it
is easy to enable and disable memoisation. I would just use a
decorator. You don't need to write one yourself. Since Python 3.2 the
standard library contains a memoisation decorator that you can use:

http://docs.python.org/dev/library/functools.html#functools.lru_cache

Presumably the place where you read about them would have listed some
example decorators that you can use for memoisation. Here's a quick
example that works for hashable inputs:

def memo(func):
table = {}
def wrapper(inputarg):
try:
return table[inputarg]
except KeyError:
table[inputarg] = val = func(inputarg)
return val
return wrapper

@memo
def square(x):
print('Calling square()')
return x ** 2

print('2**2 is %i' % square(2)) # cache miss
print('3**2 is %i' % square(3)) # cache miss
print('2**2 is %i' % square(2)) # cache hit

Output:
$ python tmp.py
Calling square()
2**2 is 4
Calling square()
3**2 is 9
2**2 is 4


Oscar
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] memoize, lookup, or KIS?

2012-11-19 Thread Steven D'Aprano

On 19/11/12 22:02, Albert-Jan Roskam wrote:

Hi,

I have a function that converts a date value, expressed as the number of
seconds sinds start of the gregorian calendar, into a human-readable format
(typically an iso-date). So if a record contains x date values, and a data
set contains y records, the number of function calls are x * y. Imagine a
 data set with 1M records with dob and enrollment_date in in it: the number
 of function calls is huge (well, 2M).


I was reading about memoize decorators the other day and I realized that
this function might benefit from memoizing, or a lookup table.



Emphasis on "might". Unless you have timed the code with or without a lookup
table, you're just guessing whether it is an optimization or a pessimization.

On the other hand, my intuition is that it *will* benefit from memoization,
so my guess is the same as your guess :)



On the other hand, it might complicate the code too much, so it might
be better to Keep It Simple (KIS). Is the code below a sound approach?



No. You should separate the cache code from the non-cache code. Decorators
are ideal for that, but even without decorators you should split the code.
See below.

Also, you should have some way to stop the lookup table from growing forever.
If you are running Python 3.3, you can use functools.lru_cache, which
implements a Least Recently Used cache. Once the cache reaches a certain size,
the element which was least recently used is flushed.

Usage is trivially simple, at least for functions, I've never used it with
methods and there may be some complications. But the usage is:

@functools.lru_cache(maxsize)
def myfunction(a, b, c):
result = some_calculation(a, b) + c  # whatever
return result

and the decorator will automatically look after storing results in the lookup
table, retrieving them afterwards, and ensuring it never gets too big.

Writing completely general purpose memoize decorators can be a bit tricky, but
you can find a whole lot of recipes here:

http://code.activestate.com/search/recipes/#q=memoize

Here's a trivial approach which doesn't use a decorator at all. The important
feature is that the caching logic isn't mixed up with the uncached logic.


class Test(object):

def __init__(self):
self._cache = {}

def clear_cache(self):
self._cache.clear()

def spss2strDate(self, gregorianDate, fmt="%Y-%m-%d", recodeSysmisTo=""):
# cached wrapper
t = (gregorianDate, fmt, recodeSysmisTo)
if t in self._cache:
# cache hit
return self._cache[t]
# otherwise cache miss
result = self._calculate_spss2strDate(*t)  # this does the real work
if len(self._cache) > 1000:
self._cache.popitem()  # discard an arbitrary (key,value) pair
self._cache[t] = result
return result

def _calculate_spss2strDate(self, gregorianDate, fmt, recodeSysmisTo):
# uncached version
return some_calculation(...)


You can fill in the details for the uncached version :)

One good improvement would be to add instrumentation[1] to the cache so you can
tell whether or not the cache is worthwhile. E.g. record how many times each
set of arguments are used. If you find that hardly any triple of arguments is
used multiple times (i.e. nearly every call is unique), then the cache is a
waste of time.



[1] A fancy term for any sort of extra data associated with the cache, such as
a count of how many cache hits and misses there are.


--
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] memoize, lookup, or KIS?

2012-11-19 Thread Albert-Jan Roskam
Hi,

I have a function that converts a date value, expressed as the number of 
seconds sinds start of the gregorian calendar, into a human-readable format 
(typically an iso-date). So if a record contains x date values, and a data set 
contains y records, the number of function calls are x * y. Imagine a data set 
with 1M records with dob and enrollment_date in in it: the number of function 
calls is huge (well, 2M). 


I was reading about memoize decorators the other day and I realized that this 
function might benefit from memoizing, or a lookup table. On the other hand, it 
might complicate the code too much, so it might be better to Keep It Simple 
(KIS). Is the code below a sound approach? I believe that, in effect, it uses a 
memoization approach (as it is a slowly growing lookup table).


import datetime

class Test(object):

    def __init__(self):
    self.isoDateLookup = {}
    self.lookupCount = 0
    
    def spss2strDate(self, gregorianDate, fmt="%Y-%m-%d", recodeSysmisTo=""):
    """ This function converts internal SPSS dates (number of seconds
    since midnight, Oct 14, 1582 (the beginning of the Gregorian calendar))
    to a human-readable format """
    MAXLOOKUP = 10**6
    try:
    if not hasattr(self, "gregorianEpoch"):
    self.gregorianEpoch = datetime.datetime(1582, 10, 14, 0, 0, 0)
    if fmt == "%Y-%m-%d" and len(self.isoDateLookup) <= MAXLOOKUP:
    try:
    result = self.isoDateLookup[gregorianDate]
    self.lookupCount += 1
    except KeyError:
    theDate = self.gregorianEpoch + 
datetime.timedelta(seconds=gregorianDate)
    result = datetime.datetime.strftime(theDate, fmt)
    self.isoDateLookup[gregorianDate] = result
    return result
    else:
    theDate = self.gregorianEpoch + 
datetime.timedelta(seconds=gregorianDate)
    return datetime.datetime.strftime(theDate, fmt)
    except OverflowError:
    return recodeSysmisTo
    except TypeError:
    return recodeSysmisTo
    except ValueError:
    return recodeSysmisTo

if __name__ == "__main__":
    import random
    t = Test()
    someDate = 11654150400.0
    aDay = 24 * 60 * 60
    random.seed(43210)
    for i in xrange(10**3):
    randDate = random.randint(0, 10**3) * random.choice([aDay, -aDay]) + 
someDate
    t.spss2strDate(randDate)
    print t.lookupCount

 
Regards,
Albert-Jan


~~
All right, but apart from the sanitation, the medicine, education, wine, public 
order, irrigation, roads, a 
fresh water system, and public health, what have the Romans ever done for us?
~~ ___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor