Python: Maksimum yineleme derinliği aşıldı


86

Aşağıdaki özyineleme kodum var, her düğümde üst düğüme ait düğümleri almak için sql sorgusunu çağırıyorum.

İşte hata:

Exception RuntimeError: 'maximum recursion depth exceeded' in <bound method DictCursor.__del__ of <MySQLdb.cursors.DictCursor object at 0x879768c>> ignored

RuntimeError: maximum recursion depth exceeded while calling a Python object
Exception AttributeError: "'DictCursor' object has no attribute 'connection'" in <bound method DictCursor.__del__ of <MySQLdb.cursors.DictCursor object at 0x879776c>> ignored

Sql sonuçlarını almak için çağırdığım yöntem:

def returnCategoryQuery(query, variables={}):
    cursor = db.cursor(cursors.DictCursor);
    catResults = [];
    try:
        cursor.execute(query, variables);
        for categoryRow in cursor.fetchall():
            catResults.append(categoryRow['cl_to']);
        return catResults;
    except Exception, e:
        traceback.print_exc();

Aslında yukarıdaki yöntemle ilgili herhangi bir sorunum yok ama yine de soruya uygun bir genel bakış sağlamak için koydum.

Özyineleme Kodu:

def leaves(first, path=[]):
    if first:
        for elem in first:
            if elem.lower() != 'someString'.lower():
                if elem not in path:
                    queryVariable = {'title': elem}
                    for sublist in leaves(returnCategoryQuery(categoryQuery, variables=queryVariable)):
                        path.append(sublist)
                        yield sublist
                    yield elem

Özyinelemeli işlevi çağırma

for key, value in idTitleDictionary.iteritems():
    for startCategory in value[0]:
        print startCategory + " ==== Start Category";
        categoryResults = [];
        try:
            categoryRow = "";
            baseCategoryTree[startCategory] = [];
            #print categoryQuery % {'title': startCategory};
            cursor.execute(categoryQuery, {'title': startCategory});
            done = False;
            while not done:
                categoryRow = cursor.fetchone();
                if not categoryRow:
                    done = True;
                    continue;
                rowValue = categoryRow['cl_to'];
                categoryResults.append(rowValue);
        except Exception, e:
            traceback.print_exc();
        try:
            print "Printing depth " + str(depth);
            baseCategoryTree[startCategory].append(leaves(categoryResults))
        except Exception, e:
            traceback.print_exc();

Sözlüğü yazdırmak için kod,

print "---Printing-------"
for key, value in baseCategoryTree.iteritems():
    print key,
    for elem in value[0]:
        print elem + ',';
    raw_input("Press Enter to continue...")
    print

Özyineleme çok derinse, özyineleme işlevimi çağırdığımda hatayı almalıyım, ancak sözlüğü yazdırdığımda bu hatayı aldığımda.


8
Özyinelemeli yerine yinelemeli olarak yeniden yazın.
Seth Carnegie

1
if first:Çek birlikte fazla for elem in first:. Sorgu boş bir sonuç listesi döndürürse, üzerinde yineleme yapmak istediğiniz gibi hiçbir şey yapmayacaktır. Ayrıca, bu listeyi bir liste anlayışı ile daha basit bir şekilde oluşturabilirsiniz (ve bu noktalı virgüller gereksizdir ve genellikle çirkin kabul edilir :))
Karl Knechtel

@KarlKnechtel noktalı virgül için üzgünüm, Python programlamaya yeni başladığımı söyleyebilir misiniz .... :)
ekle

Özür dilemene gerek yok, sana bunu yazman için para ödemiyorum :) Umarım Python'u özgürleştiriyorsundur;)
Karl Knechtel

Yanıtlar:


167

İzin verilen yığın derinliğini artırabilirsiniz - bununla, aşağıdaki gibi daha derin özyinelemeli çağrılar mümkün olacaktır:

import sys
sys.setrecursionlimit(10000) # 10000 is an example, try with different values

... Ama önce kodunuzu, örneğin özyineleme yerine yineleme kullanarak optimize etmeyi denemenizi tavsiye ederim.


1
10000 yerine satırı ekledim 30000 ekledim ancak Segmentasyon Hatası ile sonlandırdım (çekirdek döküldü) :(
add-half-colons

16
1000 olarak ayarlanmasının bir nedeni var ... Guido van Rossum'un bunun hakkında bir şeyler söylediğine inanıyorum .
Lambda Fairy

3
Öyleyse Guido'nun argümanı, düzgün kuyruk çağrısının (1) daha kötü yığın izleri sağlamasıdır - yinelemeli olarak yazdığınızda hiç çerçeve olmaması yerine? bu nasıl daha kötü? (2) Onlara güzel bir şey verirsek, ona güvenmeye başlayabilirler. (3) İnanmıyorum, Scheme gibi kokuyor. (4) Python kötü bir şekilde tasarlanmıştır, böylece bir derleyici bir şeyin kuyruk çağrısı olup olmadığını verimli bir şekilde keşfedemez. Sanırım o konuda anlaşabilir miyiz?
John Clements

1
@hajef Üçüncü olarak, kuyruk arama kesinlikle sadece listeler için değildir; herhangi bir ağaç yapısı kazanır. Bir döngüde özyinelemeli çağrılar olmadan bir ağaçta gezinmeyi deneyin; yığını elle modellemeye başlarsınız. Son olarak, Python'un asla bu şekilde tasarlanmadığı yönündeki argümanınız kesinlikle doğrudur, ancak beni bunun bir tanrı tasarımı olduğuna ikna etmek için çok az şey yapar.
John Clements

1
Van Rossum'un şapkasında özyineleme hakkında bir arı olması, yinelemenin "optimal" olmadığı anlamına gelmez: optimize ettiğiniz şeye bağlıdır!
Gene Callahan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.