بررسی و تغییر محدودیت بازگشت به پایتون (به عنوان مثال sys.setrecursionlimit)

کسب و کار

در پایتون ، محدودیت بالایی برای تعداد بازگشت ها (حداکثر تعداد بازگشت ها) وجود دارد. برای اجرای یک تابع بازگشتی با تعداد زیادی تماس ، لازم است محدودیت را تغییر دهید. از توابع موجود در ماژول sys کتابخانه استاندارد استفاده کنید.

تعداد بازگشتها نیز با توجه به اندازه پشته محدود می شود. در برخی از محیط ها ، ماژول منبع کتابخانه استاندارد را می توان برای تغییر حداکثر اندازه پشته استفاده کرد (در اوبونتو کار می کرد ، اما در ویندوز یا مک کار نمی کرد).

اطلاعات زیر در اینجا ارائه شده است.

  • حد بالایی از تعداد فعلی بازگشتها را بدست آورید:sys.getrecursionlimit()
  • محدوده بالایی تعداد بازگشت ها را تغییر دهید:sys.setrecursionlimit()
  • حداکثر اندازه پشته را تغییر دهید:resource.setrlimit()

کد نمونه در اوبونتو اجرا می شود.

دریافت محدودیت فعلی بازگشت: 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 () دقیقاً حداکثر تعداد بازگشتها نیست ، بلکه حداکثر عمق پشته مترجم پایتون است ، بنابراین حتی اگر تعداد بازگشتها کمی کمتر از این مقدار باشد ، خطا (RecursionError) مطرح شود

پایتون th 帰 限界
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

در پایتون ، ماژول منبع در کتابخانه استاندارد می تواند برای تغییر حداکثر اندازه پشته استفاده شود. با این حال ، ماژول منبع یک ماژول مخصوص یونیکس است و نمی تواند در ویندوز استفاده شود.

با استفاده از resource.getrlimit () ، می توانید محدوده منبع مشخص شده در آرگومان را به صورت چند برابر (حد نرم ، محدودیت سخت) دریافت کنید. در اینجا ما منبع.RLIMIT_STACK را به عنوان منبع تعیین می کنیم که نشان دهنده حداکثر اندازه پشته فراخوانی فرآیند جاری است.

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

در مثال ، حد نرمال 8388608 (8388608 B = 8192 KB = 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 برای یک آزمایش ساده (بدون محدودیت) تعیین شده است ، اما در حقیقت ، محدودتر کردن آن به مقدار مناسب ایمن تر است.

علاوه بر این ، هنگامی که سعی کردم محدودیت نرم افزاری نامحدودی را برای مک خود نیز تعیین کنم ، خطای زیر رخ داد.ValueError: not allowed to raise maximum limit
اجرای اسکریپت با sudo کمکی نکرد. ممکن است توسط سیستم محدود شود.

فرآیندی با UID م aثر یک کاربر فوق العاده می تواند محدودیت منطقی ، از جمله بدون محدودیت ، درخواست کند.
با این حال ، درخواستی که بیش از حد تعیین شده توسط سیستم باشد ، همچنان منجر به ایجاد ValueError می شود.
resource.setrlimit() — Resource usage information — Python 3.10.0 Documentation

ویندوز ماژول منبع ندارد و مک نمی تواند حداکثر اندازه پشته را به دلیل محدودیت های سیستم تغییر دهد. اگر بتوانیم اندازه پشته را به وسیله ای افزایش دهیم، باید بتوانیم عیب تقسیم بندی را حل کنیم، اما نتوانستیم این را تأیید کنیم.

Copied title and URL