2016-08-20 4 views
1

Python-Version: 2.7. Betriebssystem: Windows 10 64-Bit.Python versuchen/außer/sonst mit Rekursion

Hinweis: Ich habe einen Weg gefunden, um das unten beschriebene Problem zu umgehen, das keine try/except/else-Anweisungen verwendet. Ich stelle die Frage nur deshalb, weil ich neugierig bin, warum sich der Code so verhält, wie er es tut, und ob es eine Möglichkeit gibt, das zu tun, was ich versuche, indem ich try/except/else benutze.

Ich habe eine Datei blah.py, mit dem folgenden Code genannt:

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) 

Jetzt habe ich zu Powershell gehen, und Typ:

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

Es ist, was ich erwarten würde - ein Ordner namens myFolder_0 erstellt und druckt myFolder_0 und <type 'str'>. Jetzt, nach wie vor in Powershell, I-Typ:

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

Dieses Mal ist es ein Ordner macht myFolder_1 genannt, wie ich erwarten würde, aber statt den Druck myFolder_1 und <type 'str'>, druckt es None und <type 'NoneType'>. Es wird dies weiterhin jedes Mal tun, wenn ich blah.makeFolder('myFolder') verwende.

Das Verhalten ist auch seltsam anders, wenn ich die Befehle, die ich in Powershell eingegeben habe innerhalb des Skripts. Ich habe eine Datei blah2.py genannt, die die gleichen wie blah.py ist, aber mit einem Skript am Ende:

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) 

Dann in Powershell:

python blah2.py 

Dieses Mal ist es myFolder_0 und Druck myFolder_0 und <type 'str'> macht (so funktioniert der myStr Block wie in blah.py), und geht dann in eine unendliche Rekursion (so funktioniert der myStr1 Block nicht). Aus Gründen, die ich nicht verstehe, ist das Verhalten anders als während der interaktiven Sitzung. Wenn ich wieder python blah2.py tippe, macht es myFolder_1 und druckt None und <type 'NoneType'> (myStr Block), geht dann wieder in unendliche Rekursion (myStr1 Block).

Warum verhält sich das Skript anders als die interaktive Sitzung, warum findet eine unendliche Rekursion im Skript statt, und gibt es eine Version meines Codes, die try/except/else verwendet, aber funktioniert?

+0

Willkommen bei Stackoverflow! Ich möchte Sie nur dazu beglückwünschen, eine ausgezeichnete Frage zu stellen, einschließlich eines schönen kompakten Beispiels. Gut gemacht! –

+1

Wie verhält sich "Powershell" hier? Hast du gerade "Python Shell" eingegeben oder benutzt du PowerShell? – smarx

+1

'blah2.py' sieht für mich nicht richtig aus ... es führt' blah.makeFolder' aus, aber 'blah' ist nirgends definiert? – smarx

Antwort

3

Ihr Code funktioniert gut für mich, wenn ich einen return zum rekursiven Aufruf hinzu:

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 

Wie, warum Sie sehen, was Sie sehen ... es gibt auf jeden Fall etwas, was sonst hier los ist. Der Code, den Sie für blah2.py freigegeben haben, könnte möglicherweise nicht funktionieren, da blah nirgendwo definiert ist. Meine Vermutung ist, dass Sie anderen Code ausführen, ohne es zu merken. (Vielleicht eine andere Kopie der Datei in einem anderen Verzeichnis?)

+0

Beat mich dazu :), sollte er auch die entsprechende Ausnahme behandeln, die "OSError" anstelle einer Ausnahme sein würde, die jede mögliche Ausnahme abfängt – danidee

+0

Großartig, das funktioniert, danke! In Bezug auf die blah2 Zeug, zwei Dinge: Erstens, in der ursprünglichen Post gab es einen Tippfehler, meine blah2.py Datei hatte nicht blah.makeFolder, nur makeFolder. Ich werde kurz bearbeiten. Zweitens startete ich meinen Computer neu und führte ihn erneut aus, und dann fing er an, dasselbe wie die interaktive Sitzung zu tun, also denke ich, dass es etwas seltsames im Gedächtnis gab. – user3558855

0

Mein erster Gedanke ist, dass das inkonsistente Verhalten, das Sie sehen, möglicherweise ist, weil einige Verzeichnisse bereits existieren, wenn Sie sie nacheinander ausführen.Um dies zu verhindern, versuchen Sie diesen Code an den Anfang Hinzufügen alle Verzeichnisse, die von einem vorherigen Lauf erstellt, um aufzuräumen:

import os 

for dirname in [f for f in os.listdir('.') if 
       (os.path.isdir(f) and f.startswith('myFolder'))]: 
    os.rmdir(dirname) 

Aber hier ist, wie die tatsächliche Problem zu beheben:

import os 

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