Python тілінде рекурсиялар санының жоғарғы шегі бар (рекурсиялардың максималды саны). Шақырулар саны көп рекурсивті функцияны орындау үшін шекті өзгерту қажет. Стандартты кітапхананың sys модуліндегі функцияларды пайдаланыңыз.
Рекурсиялар саны стек өлшемімен де шектеледі. Кейбір орталарда стандартты кітапхананың ресурс модулін максималды стек өлшемін өзгерту үшін пайдалануға болады (ол Ubuntu жүйесінде жұмыс істеді, бірақ Windows немесе Mac жүйесінде емес).
Мұнда келесі ақпарат берілген.
- Ағымдағы рекурсиялар санының жоғарғы шегін алыңыз:
sys.getrecursionlimit()
- Рекурсиялар санының жоғарғы шегін өзгертіңіз:
sys.setrecursionlimit()
- Стектің максималды өлшемін өзгертіңіз:
resource.setrlimit()
Үлгі коды Ubuntu жүйесінде жұмыс істейді.
Ағымдағы рекурсия шегін алыңыз: sys.getrecursionlimit()
Ағымдағы рекурсия шегін sys.getrecursionlimit() арқылы алуға болады.
import sys
import resource
print(sys.getrecursionlimit())
# 1000
Мысалда рекурсиялардың максималды саны 1000 болып табылады, ол ортаңызға байланысты өзгеруі мүмкін. Мұнда импортталатын ресурс Windows жүйесінде емес, кейінірек пайдаланылатынын ескеріңіз.
Мысал ретінде біз келесі қарапайым рекурсивті функцияны қолданамыз. Егер аргумент ретінде n оң бүтін саны көрсетілсе, шақырулар саны n есе болады.
def recu_test(n):
if n == 1:
print('Finish')
return
recu_test(n - 1)
Рекурсияны жоғарғы шектен артық орындауға әрекеттенсеңіз, қате (RecursionError) көтеріледі.
recu_test(950)
# Finish
# recu_test(1500)
# RecursionError: maximum recursion depth exceeded in comparison
sys.getrecursionlimit() арқылы алынған мән қатаң түрде рекурсиялардың максималды саны емес, Python интерпретаторының максималды стек тереңдігі екенін ескеріңіз, сондықтан рекурсиялар саны осы мәннен сәл аз болса да, қате (RecursionError) пайда болады. көтерілу.
再帰限界は、再帰の限界ではなく、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
Рекурсия шегін өзгерту: sys.setrecursionlimit()
Рекурсиялар санының жоғарғы шегін sys.setrecursionlimit() арқылы өзгертуге болады. Жоғарғы шек аргумент ретінде көрсетіледі.
Тереңірек рекурсияны орындауға мүмкіндік береді.
sys.setrecursionlimit(2000)
print(sys.getrecursionlimit())
# 2000
recu_test(1500)
# Finish
Көрсетілген жоғарғы шек тым аз немесе тым үлкен болса, қате орын алады. Бұл шектеу (шектің жоғарғы және төменгі шегі) қоршаған ортаға байланысты өзгереді.
Шектеудің максималды мәні платформаға байланысты. Егер сізге терең рекурсия қажет болса, платформа қолдайтын ауқымда үлкенірек мәнді көрсетуге болады, бірақ бұл мән тым үлкен болса, апатқа әкелетінін ескеріңіз.
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
Рекурсиялардың максималды саны да келесі түсіндірілгендей стек өлшемімен шектеледі.
Стектің максималды өлшемін өзгертіңіз: resource.setrlimit()
Тіпті sys.setrecursionlimit() ішінде үлкен мән орнатылған болса да, рекурсиялар саны көп болса, ол орындалмауы мүмкін. Сегменттеу қатесі келесідей орын алады.
sys.setrecursionlimit(10 ** 9)
print(sys.getrecursionlimit())
# 1000000000
recu_test(10 ** 4)
# Finish
# recu_test(10 ** 5)
# Segmentation fault
Python тілінде стандартты кітапханадағы ресурс модулін максималды стек өлшемін өзгерту үшін пайдалануға болады. Дегенмен, ресурс модулі Unix үшін арнайы модуль болып табылады және оны Windows жүйесінде пайдалану мүмкін емес.
- Unix Specific Services — Python 3.10.0 Documentation
- resource — Resource usage information — Python 3.10.0 Documentation
resource.getrlimit() арқылы аргументте көрсетілген ресурс шегін (жұмсақ шек, қатаң шектеу) кортежі ретінде алуға болады. Мұнда біз ресурс ретінде ресурс.RLIMIT_STACK көрсетеміз, ол ағымдағы процестің шақыру стекінің ең үлкен өлшемін көрсетеді.
- resource.getrlimit() — Resource usage information — Python 3.10.0 Documentation
- resource.RLIMIT_STACK — Resource usage information — Python 3.10.0 Documentation
print(resource.getrlimit(resource.RLIMIT_STACK))
# (8388608, -1)
Мысалда жұмсақ шектеу 8388608 (8388608 B = 8192 КБ = 8 МБ) және қатаң шектеу -1 (шексіз).
Ресурс шегін resource.setrlimit() арқылы өзгертуге болады. Мұнда жұмсақ шектеу де -1 (шектеусіз) мәніне орнатылған. Сондай-ақ, шектеусіз шектеуді көрсету үшін тұрақты ресурс.RLIM_INFINIT пайдалануға болады.
Стек өлшемі өзгергенге дейін сегменттеу қателігіне байланысты орындалмайтын терең рекурсия енді орындалуы мүмкін.
resource.setrlimit(resource.RLIMIT_STACK, (-1, -1))
print(resource.getrlimit(resource.RLIMIT_STACK))
# (-1, -1)
recu_test(10 ** 5)
# Finish
Мұнда жұмсақ шек қарапайым эксперимент үшін -1 (шексіз) мәніне орнатылған, бірақ шын мәнінде оны сәйкес мәнге шектеу қауіпсіз болар еді.
Сонымен қатар, мен Mac компьютерімде де шектеусіз жұмсақ шектеу орнатуға тырысқанда, келесі қате орын алды.ValueError: not allowed to raise maximum limit
Сценарийді sudo көмегімен іске қосу көмектеспеді. Ол жүйемен шектелуі мүмкін.
Суперпайдаланушының тиімді UID идентификаторы бар процесс кез келген ақылға қонымды шектеуді, соның ішінде шектеуді сұрай алады.
Дегенмен, жүйе жүктеген шектеуден асатын сұрау бәрібір ValueError нәтижесіне әкеледі.
resource.setrlimit() — Resource usage information — Python 3.10.0 Documentation
Windows жүйесінде ресурс модулі жоқ және жүйе шектеулеріне байланысты Mac жүйесінде максималды стек өлшемін өзгерте алмады. Егер біз стек өлшемін қандай да бір жолмен ұлғайта алсақ, сегменттеу ақауын шеше алуымыз керек, бірақ біз мұны растай алмадық.