Search code examples
pythonexecution

Python 2.7.11 os.rename issues and weird execution order


I'm trying to write a simple script to check if a file has numbers in its name, and to delete them if it does. Here's my code:

import os

directory = raw_input("Enter a path string: ")
print "This will now delete all numbers from the files in %s." %directory

for filename in os.listdir(directory):
    print filename
    for s in filename:
        if s.isdigit():
            print filename
            path = os.path.join(directory, filename)
            print path
            target = os.path.join(directory, filename.replace(s, ""))
            print target
            os.rename(path, target)

print "Done."

When I run it I get the following error:

Traceback (most recent call last):
File "EditFilename.py", line 15, in <module>
os.rename(path, target)
NameError: name 'path' is not defined

Which is weird, since path is clearly defined. If I define path above the for loop as path = "Nothing" then I get this error:

File "EditFilename.py", line 16, in <module>
os.rename(path, target)
OSError: [Errno 2] No such file or directory

I'm following what apparently worked from this link, but I can't get my code to work. It seems like the line os.rename(path, target) is being executed before the line path = os.path.join(directory, filename)!

Thanks in advance for your help, after four hours of google I don't know what to do.


Solution

  • Looking at the markup source of your question, it seems like you are mixing tabs and spaces for your Python indentation. Don't do this! This can severely confuse your Python interpreter and cause individual lines to be associated with different blocks than they should be.

    It's difficult to determine how exactly your indentation was, because of the extra-indentation for the code block in the question, however, the first three lines in your if block as indented with 3 tabs and 4 spaces, and the following three lines with 8 spaces, 1 tab, and 4 more spaces.

    Thus, what your Python interpreter is seeing is probably more like this:

    for s in filename:
        if s.isdigit():
            print filename
            path = os.path.join(directory, filename)
            print path
        target = os.path.join(directory, filename.replace(s, ""))
        print target
        os.rename(path, target)
    

    That is, the os.rename line is always executed, even if path was not previously defined in the if block, and if you define path = "Nothing" at the start, it will still have that value when Python hits the first os.rename.

    To fix this, simply convert all the indentation to either tabs or spaces (which to use is somewhat a question of taste). Most text editors will do this for you if just indent and then de-dent everything (i.e. press Ctrl-A, Tab, Shift-Tab).