2

A function for returning sum of the sizes of its arguments which could be single file/directory or a list of files/directories, is given below. The code gives an error message RuntimeError: maximum recursion depth exceeded while calling a Python object however I try to test this.

How to fix this?

Thanks

suresh

#!/usr/bin/python3.1
import os

def fileSizes(f):
    if hasattr(f,'__iter__'):
        return sum(filter(fileSizes,f))
    if os.path.isfile(f):
        return os.path.getsize(f)
    elif os.path.isdir(f):
        total_size = os.path.getsize(f)
        for item in os.listdir(f):
            total_size += fileSizes(os.path.join(f, item))
        return total_size
2
  • does listdir include current directories? what are the iterables that you are looping over? Commented Aug 29, 2011 at 1:02
  • os.listdir() does not include current or parent directory. Commented Aug 29, 2011 at 1:07

4 Answers 4

9

Instead of writing your own adhoc directory-transversal method, use the built-in os.walk (Documentation) method.

In fact, the example in the documentation (link above) computes the total size of non-directory files.

Sign up to request clarification or add additional context in comments.

2 Comments

But os.walk() calls listdir() in turn right? I am using listdir() in the above code..So can it still be called adhoc?
os.walk calls os.listdir(), it behaves the same way as your code, but iteratively, and also, allowing to follow/ignore symlinks. You should really take a look at the documentation, everything is clear there.
3

Last time I checked, the default maximum recursion depth was 1000. You have a few options:

  1. Use Stackless Python which imposes no recursion limit (allowing infinite recursion).
  2. Rewrite your function in an iterative style rather than recursive, so you don't overflow the stack in the first place.
  3. Set the maximum recursion limit with sys.setrecursionlimit. Beware that this can cause a segmentation fault if abused.

3 Comments

-1: setting sys.setrecursionlimit in a program is not safe and can cause segfaults. The only time when that's correct is when you're writing a one-time use script. :/
@Devin doesn't mean I can't tell him it's an option.
@Devin should we never use C because every C program you write is "potentially segfaulting?" I'll switch the order and add a warning if it makes you feel better.
1

The problem is in the line:

if hasattr(f,'__iter__'):
    return sum(filter(fileSizes,f))

Since f is a path, it is a string, and it has the attribute __iter__, so you loop there infinitely.

6 Comments

Oh, then how can I test for list which is not valid for a string? Okay I can use isinstance() I believe....
did that fix your problem? about your second question, you could try type(f) != str and hasattr(f,'__iter__') ...
@rm I used isinstance. Recursion issue is gone but the sum(filter(...)) is giving me some other kind of errors...
Great, I fixed your original code then. Try to fix the rest yourself or ask here in another question.
Okay, this is a different question now, (not what the comments are meant for), but I think you mean to use a map in your code, not a filter. If you have any other question, ask other questions, don't keep adding them in the comments.
|
1

There are many tricks to avoid problems with deep recursion, but I suspect that is not your core issue. (Maybe it is if you have very deep directory structures.. so test on a shallow directory first).

I'm guessing you're finding a cyclical structure in your directory tree caused by links. I.e. a symlinked directory pointing back into a parent directory. (This kind of structure is not unusual).

You can avoid the infinite loop by checking whether a directory is a symlink before following it.

Another posibility is that you're getting "." or ".." somewhere in your lists. These will also generate infinite loops. I don't see that happening here, but its worth thinking about. os.listdir doesn't seem to return them.

2 Comments

@Anderson, I tried running on a shallow directory, but it looks like, irrespective of the argument, the code gives the same error message. So I cant test it as of now ...
Running your code "as is" in my directory produces results - in particular I tried fileSize(".") in a couple of directories. But the results look wrong.. (For example I get 68 when run in an empty directory).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.