[Tutor] MemoryError

Jeff Shannon jeff at ccvcorp.com
Wed Dec 8 21:29:10 CET 2004


Liam Clarke wrote:

> Hi all, 
> 
> I'm playing with a file, and attempting to replace a section with a
> string, and using the following command -
> 
> seg=codeSt[element:endInd+len(endStr]
> codeSt=codeSt.replace(seg, hrefString)
> 
> At the replace, I get a MemoryError. It's part of a for loop, but it
> gives the error the first time around.


I'm not sure why you're getting the MemoryError, but it'd be easier to 
figure out if you posted the entire text of the traceback.

A few other pointers --

You'll probably get better performance if you put all of this code 
inside of a function.  Even if you're only running it once, putting it 
in a function allows the interpreter to do some optimization tricks on 
locals() which can't be done at the module-global level (where you're 
running now).  It's just barely possible that just doing this will 
help with your MemoryError problem.  (You would probably benefit from 
splitting it into multiple functions, actually.  I'd have the code 
that finds text and url values each in their own function, for example.)

Try adding a line in between those two that prints out the value of 
element and endInd, and then check that those numbers really are valid 
indexes into codeSt.  While you're at it, print out hrefString and 
make sure it looks like it's supposed to.

At the start of your program, you have the following:

     inp=file("toolkit.txt","r")
     codeSt=inp.readlines()
     inp.close()
     codeSt="".join(codeSt)

Since you're not processing by lines, and are explicitly joining all 
the lines together, why have Python separate them for you?  It would 
be much more efficient to simply use 'codeSt = inp.read()', with no 
need to join() afterwards.  The readlines() method effectively does a 
read() followed by splitting the result into lines; for your purposes, 
there's no point in splitting the lines if you're just going to join() 
them immediately.

Instead of finding the start and end index of the segment you want to 
replace, making a copy of that segment, and then scanning your 
original string to replace that segment with a new chunk, it would 
probably make more sense to simply grab codeSt before the segment and 
after the segment and concatenate them with the new chunk.  Thus, your 
two lines above become

     codeSt = codeSt[:element] + hrefString \
                      + codeSt[endInd+len(endStr)]

Once again, this would avoid doing the same work twice.

> Now, I had imagined that codeSt=codeSt+10 would destroy the old codeSt
> in memory and create a new codeSt. Am I right?

Actually, this will probably raise a TypeError (cannot concatenate 
'str' and 'int' objects).  ;)  But yes, rebinding codeSt to a new 
string should allow the old string to be destroyed (if there are no 
other references to it).

Hope that this helps.

Jeff Shannon
Technician/Programmer
Credit International




More information about the Tutor mailing list