ពិនិត្យ និងផ្លាស់ប្តូរដែនកំណត់ការហៅឡើងវិញ Python (ឧ. sys.setrecursionlimit)

អាជីវកម្ម

នៅក្នុង Python មានដែនកំណត់ខាងលើចំពោះចំនួននៃការផ្សាយឡើងវិញ (ចំនួនអតិបរមានៃការផ្សាយឡើងវិញ)។ ដើម្បី​ប្រតិបត្តិ​មុខងារ​ហៅ​ចេញ​ជា​មួយ​ចំនួន​ច្រើន វា​ចាំបាច់​ត្រូវ​ផ្លាស់​ប្តូរ​កម្រិត​កំណត់។ ប្រើមុខងារនៅក្នុងម៉ូឌុល sys នៃបណ្ណាល័យស្តង់ដារ។

ចំនួននៃការធ្វើឡើងវិញក៏ត្រូវបានកំណត់ដោយទំហំជង់ផងដែរ។ នៅក្នុងបរិយាកាសមួយចំនួន ម៉ូឌុលធនធាននៃបណ្ណាល័យស្តង់ដារអាចត្រូវបានប្រើដើម្បីផ្លាស់ប្តូរទំហំជង់អតិបរមា (វាដំណើរការលើអ៊ូប៊ុនទូ ប៉ុន្តែមិនមែននៅលើ Windows ឬ mac ទេ)។

ព័ត៌មានខាងក្រោមត្រូវបានផ្តល់ជូននៅទីនេះ។

  • ទទួលបានដែនកំណត់ខាងលើនៃចំនួនការផ្សាយឡើងវិញបច្ចុប្បន្ន៖sys.getrecursionlimit()
  • ផ្លាស់ប្តូរដែនកំណត់ខាងលើនៃចំនួននៃការផ្សាយឡើងវិញ៖sys.setrecursionlimit()
  • ផ្លាស់ប្តូរទំហំអតិបរមានៃជង់៖resource.setrlimit()

កូដគំរូកំពុងដំណើរការលើអ៊ូប៊ុនទូ។

ទទួលបានដែនកំណត់ការហៅឡើងវិញបច្ចុប្បន្ន៖ sys.getrecursionlimit()

ដែនកំណត់ការហៅឡើងវិញបច្ចុប្បន្នអាចទទួលបានជាមួយ sys.getrecursionlimit()។

import sys
import resource

print(sys.getrecursionlimit())
# 1000

ក្នុងឧទាហរណ៍ ចំនួនអតិបរមានៃការផ្សាយឡើងវិញគឺ 1000 ដែលអាចប្រែប្រួលអាស្រ័យលើបរិយាកាសរបស់អ្នក។ ចំណាំថាធនធានដែលយើងកំពុងនាំចូលនៅទីនេះនឹងត្រូវបានប្រើនៅពេលក្រោយ ប៉ុន្តែមិនមែននៅលើ Windows ទេ។

ជាឧទាហរណ៍ យើងនឹងប្រើមុខងារ recursive សាមញ្ញខាងក្រោម។ ប្រសិនបើចំនួនគត់វិជ្ជមាន 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 ម៉ូឌុលធនធាននៅក្នុងបណ្ណាល័យស្តង់ដារអាចត្រូវបានប្រើដើម្បីផ្លាស់ប្តូរទំហំជង់អតិបរមា។ ទោះយ៉ាងណាក៏ដោយ ម៉ូឌុលធនធានគឺជាម៉ូឌុលជាក់លាក់របស់យូនីក ហើយមិនអាចប្រើនៅលើវីនដូបានទេ។

ជាមួយនឹង resource.getrlimit() អ្នកអាចទទួលបានដែនកំណត់នៃធនធានដែលបានបញ្ជាក់នៅក្នុងអាគុយម៉ង់ជា tuple នៃ (ដែនកំណត់ទន់ ដែនកំណត់រឹង)។ នៅទីនេះ យើងបញ្ជាក់ resource.RLIMIT_STACK ជាធនធាន ដែលតំណាងឱ្យទំហំអតិបរមានៃការហៅជង់នៃដំណើរការបច្ចុប្បន្ន។

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

ក្នុងឧទាហរណ៍ ដែនកំណត់ទន់គឺ 8388608 (8388608 B = 8192 KB = 8 MB) ហើយដែនកំណត់រឹងគឺ -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 ដ៏មានប្រសិទ្ធភាពនៃអ្នកប្រើប្រាស់ជាន់ខ្ពស់អាចស្នើសុំដែនកំណត់សមហេតុផលណាមួយ រួមទាំងគ្មានដែនកំណត់ផងដែរ។
ទោះយ៉ាងណាក៏ដោយ សំណើដែលលើសពីដែនកំណត់ដែលកំណត់ដោយប្រព័ន្ធនឹងនៅតែបណ្តាលឱ្យមានកំហុសតម្លៃ។
resource.setrlimit() — Resource usage information — Python 3.10.0 Documentation

Windows មិនមានម៉ូឌុលធនធានទេ ហើយ mac មិនអាចផ្លាស់ប្តូរទំហំជង់អតិបរមាបានទេ ដោយសារការកំណត់ប្រព័ន្ធ។ ប្រសិនបើយើងអាចបង្កើនទំហំជង់ដោយមធ្យោបាយមួយចំនួន យើងគួរតែអាចដោះស្រាយកំហុសនៃការបែងចែក ប៉ុន្តែយើងមិនអាចបញ្ជាក់រឿងនេះបានទេ។

Copied title and URL