Python özyineleme sınırını kontrol edin ve değiştirin (ör. sys.setrecursionlimit)

Python’da özyineleme sayısının bir üst sınırı vardır (maksimum özyineleme sayısı). Çok sayıda çağrı ile özyinelemeli bir işlevi yürütmek için limiti değiştirmek gerekir. Standart kitaplığın sys modülündeki işlevleri kullanın.

Özyineleme sayısı da yığın boyutu ile sınırlıdır. Bazı ortamlarda, standart kitaplığın kaynak modülü maksimum yığın boyutunu değiştirmek için kullanılabilir (Ubuntu’da çalıştı, ancak Windows veya mac’ta çalışmadı).

Aşağıdaki bilgiler burada verilmiştir.

  • Geçerli yineleme sayısının üst sınırını alın:sys.getrecursionlimit()
  • Özyineleme sayısının üst sınırını değiştirin:sys.setrecursionlimit()
  • Yığının maksimum boyutunu değiştirin:resource.setrlimit()

Örnek kod Ubuntu’da çalışıyor.

Geçerli özyineleme sınırını alın: sys.getrecursionlimit()

Geçerli özyineleme sınırı, sys.getrecursionlimit() ile elde edilebilir.

import sys
import resource

print(sys.getrecursionlimit())
# 1000

Örnekte, ortamınıza bağlı olarak değişebilen maksimum yineleme sayısı 1000’dir. Buraya aktardığımız kaynağın daha sonra kullanılacağını, ancak Windows’ta kullanılamayacağını unutmayın.

Örnek olarak, aşağıdaki basit özyinelemeli işlevi kullanacağız. Argüman olarak pozitif bir n tamsayı belirtilirse, çağrı sayısı n kez olacaktır.

def recu_test(n):
    if n == 1:
        print('Finish')
        return
    recu_test(n - 1)

Üst sınırdan fazla özyineleme yapmaya çalışırsanız bir hata (RecursionError) ortaya çıkar.

recu_test(950)
# Finish

# recu_test(1500)
# RecursionError: maximum recursion depth exceeded in comparison

sys.getrecursionlimit() tarafından elde edilen değerin kesinlikle maksimum özyineleme sayısı değil, Python yorumlayıcısının maksimum yığın derinliği olduğuna dikkat edin, bu nedenle özyineleme sayısı bu değerden biraz daha az olsa bile, bir hata (RecursionError) olacaktır. yükseltilecek.

再帰限界は、再帰の限界ではなく、pythonインタープリタのスタックの最大深度です。
python – Max recursion is not exactly what sys.getrecursionlimit() claims. How come? – Stack Overflow

# recu_test(995)
# RecursionError: maximum recursion depth exceeded while calling a Python object

Özyineleme sınırını değiştir: sys.setrecursionlimit()

Özyineleme sayısının üst sınırı sys.setrecursionlimit() tarafından değiştirilebilir. Üst sınır bir argüman olarak belirtilir.

Daha derin özyinelemenin gerçekleştirilmesine izin verir.

sys.setrecursionlimit(2000)

print(sys.getrecursionlimit())
# 2000

recu_test(1500)
# Finish

Belirtilen üst limit çok küçük veya çok büyük ise hata oluşur. Bu kısıtlama (sınırın kendisinin üst ve alt limitleri) ortama bağlı olarak değişir.

Maksimum limit değeri platforma bağlıdır. Derin özyinelemeye ihtiyacınız varsa, platform tarafından desteklenen aralık içinde daha büyük bir değer belirtebilirsiniz, ancak bu değerin çok büyük olması durumunda çökmeye neden olacağını unutmayın.
If the new limit is too low at the current recursion depth, a RecursionError exception is raised.
sys.setrecursionlimit() — System-specific parameters and functions — Python 3.10.0 Documentation

sys.setrecursionlimit(4)
print(sys.getrecursionlimit())
# 4

# sys.setrecursionlimit(3)
# RecursionError: cannot set the recursion limit to 3 at the recursion depth 1: the limit is too low

sys.setrecursionlimit(10 ** 9)
print(sys.getrecursionlimit())
# 1000000000

# sys.setrecursionlimit(10 ** 10)
# OverflowError: signed integer is greater than maximum

Azami özyineleme sayısı ayrıca aşağıda açıklandığı gibi yığın boyutuyla da sınırlıdır.

Yığının maksimum boyutunu değiştirin: resource.setrlimit()

sys.setrecursionlimit() içinde büyük bir değer ayarlansa bile, özyineleme sayısı büyükse yürütülmeyebilir. Aşağıdaki gibi bir segmentasyon hatası oluşur.

sys.setrecursionlimit(10 ** 9)
print(sys.getrecursionlimit())
# 1000000000
recu_test(10 ** 4)
# Finish

# recu_test(10 ** 5)
# Segmentation fault

Python’da, maksimum yığın boyutunu değiştirmek için standart kitaplıktaki kaynak modülü kullanılabilir. Ancak kaynak modülü, Unix’e özgü bir modüldür ve Windows’ta kullanılamaz.

resource.getrlimit() ile, bağımsız değişkende belirtilen kaynağın sınırını (yumuşak limit, sabit limit) demeti olarak alabilirsiniz. Burada, mevcut işlemin çağrı yığınının maksimum boyutunu temsil eden kaynak olarak resource.RLIMIT_STACK’i belirtiyoruz.

print(resource.getrlimit(resource.RLIMIT_STACK))
# (8388608, -1)

Örnekte, yumuşak limit 8388608 (8388608 B = 8192 KB = 8 MB) ve sabit limit -1’dir (sınırsız).

Resource.setrlimit() ile kaynağın limitini değiştirebilirsiniz. Burada, yumuşak limit de -1 (sınır yok) olarak ayarlanmıştır. Sınırsız limiti temsil etmek için sabit resource.RLIM_INFINIT’i de kullanabilirsiniz.

Yığın boyutu değişikliğinden önce segmentasyon hatası nedeniyle gerçekleştirilemeyen derin özyineleme artık gerçekleştirilebilir.

resource.setrlimit(resource.RLIMIT_STACK, (-1, -1))

print(resource.getrlimit(resource.RLIMIT_STACK))
# (-1, -1)

recu_test(10 ** 5)
# Finish

Burada, basit bir deney için yumuşak sınır -1 (sınır yok) olarak ayarlanır, ancak gerçekte bunu uygun bir değerle sınırlamak daha güvenli olacaktır.

Ayrıca mac’uma da sınırsız soft limit koymaya çalıştığımda aşağıdaki hata oluştu.ValueError: not allowed to raise maximum limit
Komut dosyasını sudo ile çalıştırmak yardımcı olmadı. Sistem tarafından kısıtlanmış olabilir.

Bir süper kullanıcının etkin UID’sine sahip bir süreç, limitsiz olmak üzere herhangi bir makul limit talep edebilir.
Ancak, sistem tarafından belirlenen sınırı aşan bir istek yine de ValueError ile sonuçlanacaktır.
resource.setrlimit() — Resource usage information — Python 3.10.0 Documentation

Windows’ta bir kaynak modülü yoktur ve mac, sistem sınırlamaları nedeniyle maksimum yığın boyutunu değiştiremedi. Yığın boyutunu bir şekilde artırabilirsek, segmentasyon hatasını çözebiliriz, ancak bunu onaylayamadık.

Copied title and URL