تحقق من حد عودية Python وقم بتغييره (مثل sys.setrecursionlimit)

اعمال

في بايثون ، يوجد حد أعلى لعدد العودية (الحد الأقصى لعدد العودية). لتنفيذ وظيفة تكرارية مع عدد كبير من المكالمات ، من الضروري تغيير الحد. استخدم الوظائف الموجودة في الوحدة النمطية sys للمكتبة القياسية.

عدد العودية محدود أيضًا بحجم المكدس. في بعض البيئات ، يمكن استخدام وحدة الموارد للمكتبة القياسية لتغيير الحد الأقصى لحجم المكدس (عملت على Ubuntu ، ولكن ليس على Windows أو mac).

يتم توفير المعلومات التالية هنا.

  • احصل على الحد الأعلى للعدد الحالي من العودية: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 () ليست بالضبط الحد الأقصى لعدد العودية ، ولكن الحد الأقصى لعمق المكدس لمترجم Python ، لذلك حتى إذا كان عدد العادات أقل قليلاً من هذه القيمة ، فإن الخطأ (RecursionError) سوف تثار.

再 帰 限界 は 、 再 帰 の 限界 で は な く 、 بيثون イ ン タ ー プ リ タ の タ タ ッ ク の 最大 深度 で す。
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.

باستخدام Resource.getrlimit () ، يمكنك الحصول على حد المورد المحدد في الوسيطة كمجموعة من (soft limit، hard limit). هنا ، نحدد Resource.RLIMIT_STACK كمورد ، والذي يمثل الحجم الأقصى لمكدس الاستدعاءات للعملية الحالية.

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 لم يساعد. قد يكون مقيدًا من قبل النظام.

يمكن للعملية ذات المعرف الفريد الفعال للمستخدم المتميز أن تطلب أي حد معقول ، بما في ذلك عدم وجود حد.
ومع ذلك ، فإن الطلب الذي يتجاوز الحد الذي يفرضه النظام سيظل ينتج عنه خطأ في القيمة.
resource.setrlimit() — Resource usage information — Python 3.10.0 Documentation

لا يحتوي Windows على وحدة موارد ، ولا يمكن لنظام mac تغيير الحد الأقصى لحجم المكدس بسبب قيود النظام. إذا تمكنا من زيادة حجم المكدس ببعض الوسائل ، فسنكون قادرين على حل خطأ التجزئة ، لكننا لم نتمكن من تأكيد ذلك.

Copied title and URL