user3558855 user3558855 - 3 months ago 12
Python Question

python try/except/else with recursion

Python version: 2.7. OS: Windows 10 64-bit.

Note: I have found a way around the issue described below that doesn't use try/except/else statements. I am asking the question below only because I am curious as to why the code behaves the way it does, and if there is a way to do what I am trying to do using try/except/else.

I have a file called

blah.py
, with the following code:

import os

def makeFolder(dirName, num = 0):
try:
os.mkdir(dirName + '_' + str(num)) #error if argument of os.mkdir already exists
except:
makeFolder(dirName, num = num + 1)
else:
return dirName + '_' + str(num)


Now I go to Powershell, and type:

import blah
myStr = blah.makeFolder('myFolder')
print myStr
print type(myStr)


It does what I would expect - a folder called myFolder_0 is created, and it prints
myFolder_0
and
<type 'str'>
. Now, still in Powershell, I type:

myStr1 = blah.makeFolder('myFolder')
print myStr1
print type(myStr1)


This time it makes a folder called myFolder_1, as I expect, but instead of printing
myFolder_1
and
<type 'str'>
, it prints
None
and
<type 'NoneType'>
. It will continue doing this every subsequent time I use
blah.makeFolder('myFolder')
.

The behavior is also weirdly different if I put the commands I typed in Powershell inside of the script. I made a file called
blah2.py
, which is the same as
blah.py
, but with a script at the end:

import os

def makeFolder(dirName, num = 0):
try:
os.mkdir(dirName + '_' + str(num)) #error if argument of os.mkdir already exists
except:
makeFolder(dirName, num = num + 1)
else:
return dirName + '_' + str(num)

myStr = makeFolder('myFolder')
print myStr
print type(myStr)

myStr1 = makeFolder('myFolder')
print myStr1
print type(myStr1)


Then in Powershell:

python blah2.py


This time it makes myFolder_0 and prints
myFolder_0
and
<type 'str'>
, (so the
myStr
block works as in
blah.py
), and then goes into an infinite recursion (so the
myStr1
block doesn't work). So for reasons I don't understand, the behavior is different than it is during the interactive session. If I type
python blah2.py
again, it makes myFolder_1 and prints
None
and
<type 'NoneType'>
(
myStr
block), then goes into infinite recursion again (
myStr1
block).

Why does the script behave differently than the interactive session, why does infinite recursion happen in the script, and is there a version of my code that still uses try/except/else, but works?

Answer

Your code works fine for me if I add a return to the recursive call:

import os

def makeFolder(dirName, num = 0):
    try:
        os.mkdir(dirName + '_' + str(num))
    except OSError:
        return makeFolder(dirName, num = num + 1)
    else:
        return dirName + '_' + str(num)

print(makeFolder('myFolder')) # myFolder_0
print(makeFolder('myFolder')) # myFolder_1

As to why you're seeing what you're seeing... there's definitely something else going on here. The code you shared for blah2.py couldn't possibly work, since blah isn't defined anywhere. My guess is that you're running different code without realizing it. (Maybe a different copy of the file in a different directory?)