Athugaðu og breyttu Python endurtekningarmörkum (t.d. sys.setrecursionlimit)

Viðskipti

Í Python eru efri mörk á fjölda endurtekningar (hámarksfjöldi endurtekningar). Til að framkvæma endurkvæma aðgerð með miklum fjölda símtala er nauðsynlegt að breyta takmörkunum. Notaðu aðgerðirnar í sys einingu staðlaða bókasafnsins.

Fjöldi endurtekningar er einnig takmarkaður af staflastærðinni. Í sumum umhverfi er hægt að nota auðlindareiningu staðlaða bókasafnsins til að breyta hámarksstærð stafla (það virkaði á Ubuntu, en ekki á Windows eða Mac).

Eftirfarandi upplýsingar eru veittar hér.

  • Fáðu efri mörk núverandi fjölda endurtekningar:sys.getrecursionlimit()
  • Breyttu efri mörkum fjölda endurtekningar:sys.setrecursionlimit()
  • Breyttu hámarksstærð stafla:resource.setrlimit()

Dæmiskóðinn er í gangi á Ubuntu.

Fáðu núverandi endurtekningarmörk: sys.getrecursionlimit()

Núverandi endurtekningarmörk er hægt að fá með sys.getrecursionlimit().

import sys
import resource

print(sys.getrecursionlimit())
# 1000

Í dæminu er hámarksfjöldi endurtekningar 1000, sem getur verið mismunandi eftir umhverfi þínu. Athugaðu að tilföngin sem við erum að flytja hingað inn verða notuð síðar, en ekki á Windows.

Sem dæmi munum við nota eftirfarandi einfalda endurkvæma aðgerð. Ef jákvæð heil tala n er tilgreind sem rök, verður fjöldi kalla n sinnum.

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

Villa (RecursionError) kemur upp ef þú reynir að framkvæma endurkomu meira en efri mörkin.

recu_test(950)
# Finish

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

Athugaðu að gildið sem fæst með sys.getrecursionlimit() er ekki stranglega hámarksfjöldi endurtekningar, heldur hámarks stafladýpt Python túlksins, þannig að jafnvel þótt fjöldi endurtekningar sé aðeins minni en þetta gildi, mun villa (RecursionError) vera hækkaður.

再帰限界は、再帰の限界ではなく、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

Breyta endurtekningarmörkum: sys.setrecursionlimit()

Efri mörk fjölda endurtekningar er hægt að breyta með sys.setrecursionlimit(). Efri mörk eru tilgreind sem rök.

Gerir kleift að framkvæma dýpri endurkomu.

sys.setrecursionlimit(2000)

print(sys.getrecursionlimit())
# 2000

recu_test(1500)
# Finish

Ef tilgreind efri mörk eru of lítil eða of stór mun villa koma upp. Þessi þvingun (efri og neðri mörk mörkanna sjálfra) er mismunandi eftir umhverfinu.

Hámarksgildi hámarks fer eftir vettvangi. Ef þú þarft djúpa endurtekningu geturðu tilgreint stærra gildi innan þess bils sem pallurinn styður, en hafðu í huga að þetta gildi mun valda hruni ef það er of stórt.
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

Hámarksfjöldi endurtekningar er einnig takmarkaður af staflastærðinni, eins og útskýrt er næst.

Breyttu hámarksstærð stafla: resource.setrlimit()

Jafnvel þó að mikið gildi sé stillt í sys.setrecursionlimit() er ekki víst að það sé keyrt ef fjöldi endurtekningar er mikill. Misskipting á sér stað sem hér segir.

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

# recu_test(10 ** 5)
# Segmentation fault

Í Python er hægt að nota auðlindareininguna í staðlaða bókasafninu til að breyta hámarksstærð stafla. Hins vegar er auðlindareiningin Unix-sértæk eining og ekki hægt að nota hana á Windows.

Með resource.getrlimit() geturðu fengið takmörk auðlindarinnar sem tilgreind eru í röksemdafærslunni sem tuple of (mjúk takmörk, hörð mörk). Hér tilgreinum við resource.RLIMIT_STACK sem auðlindina, sem táknar hámarksstærð símtalastafla núverandi ferlis.

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

Í dæminu eru mjúku mörkin 8388608 (8388608 B = 8192 KB = 8 MB) og hörðu mörkin eru -1 (ótakmarkað).

Þú getur breytt mörkum tilföngsins með resource.setrlimit(). Hér eru mjúku mörkin einnig stillt á -1 (engin takmörk). Þú getur líka notað stöðuga tilföng.RLIM_INFINIT til að tákna ótakmarkaða mörkin.

Nú er hægt að framkvæma djúpa endurkomu, sem ekki var hægt að framkvæma vegna greiningarbilunar fyrir breytingu á staflastærð.

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

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

recu_test(10 ** 5)
# Finish

Hér eru mjúku mörkin sett á -1 (engin takmörk) fyrir einfalda tilraun, en í raun og veru væri öruggara að takmarka það við viðeigandi gildi.

Að auki, þegar ég reyndi að setja ótakmarkað mjúk takmörk á Mac minn líka, kom eftirfarandi villa upp.ValueError: not allowed to raise maximum limit
Það hjálpaði ekki að keyra handritið með sudo. Það gæti verið takmarkað af kerfinu.

Ferli með virku UID ofurnotanda getur beðið um hvaða hæfileg mörk sem er, þar með talið engin takmörk.
Hins vegar mun beiðni sem fer yfir mörkin sem kerfið setur samt leiða til ValueError.
resource.setrlimit() — Resource usage information — Python 3.10.0 Documentation

Windows er ekki með auðlindareiningu og mac gat ekki breytt hámarksstaflastærð vegna takmarkana á kerfinu. Ef við getum aukið staflastærðina með einhverjum hætti ættum við að geta leyst skiptingarkenninguna en við höfum ekki getað staðfest þetta.

Copied title and URL