Pythonの再帰読み出しの上限を増やしてみた。

はじめに

こんにちは。Py+honです。

この記事は東京大学工学部電気電子工学科、電子情報工学科3年後期実験の「大規模ソフトウェアを手探る」のレポートとして書かれています。

本記事では、そのうちのPython再帰読み出しの上限を変えることを目的に悪戦苦闘した様子を書きました。

 

他にも

イテラブルに頼らないfor文を使えるようにする

Pythonにイテラブルに頼らないfor文を追加してみた。

異なる型比較をした時に警告が出るようにする

Python 3で異なるデータ型を等価比較したときに警告を表示する機能を追加してみた - d01phnのブログ

rep文を使えるようにする

Pythonをいじっていろんな機能を追加してみた。

 

まとめの記事

Pythonをいじっていろんな機能を追加してみた。

ことを触ってみました。これは他の記事に書かれているのでみてみてください。

 

本実験のホームページはこちらです。

https://doss.eidos.ic.i.u-tokyo.ac.jp/

 

環境

OS:  Mac Catalina 10.15.7

エディタ: VScode

 

ビルドについて

ビルドについては以下に書いてあります。

Pythonをいじっていろんな機能を追加してみた。

これに加えて、執筆者が陥ったことについて書いておきます。

 

$ configure: error: in `/Users/gnuplot-5.0.1':
$ configure: error: C compiler cannot create executables

 

みたいなエラーが出てconfigureできない状態になりましたが、

  • Command_Line_Tools_for_Xcode_12.dmg
  • Xcode_12.xip

を入れればできました。単純にCコンパイラーに入っていないツールがあったようです。Pythonのページをちゃんと読めば書いてあるかも。

その後は普通にmakeとmake installでうまくビルドできました。

変更について

はじめに

Pythonの再帰上限は実は1000くらいで、それ以降はErrorになるようにできています。

ちなみに、GCC 5.2では900回、Clang 3.7では256回がデフォルトらしいです。

Pythonに関して、この再帰上限を増やしてみようという、Pythonをいじる簡単なものとしてやってみようと触ってみました。

変更箇所

ceval.cの436行目に以下のような箇所があった

# ceval.c
#ifndef Py_DEFAULT_RECURSION_LIMIT
#define Py_DEFAULT_RECURSION_LIMIT 1000
#endif

ここの1000の箇所を3000とかにすれば解決!と思いました。

実行後

僕の環境では、1000から3000への変更をした後、2000くらいまでは再帰ができるようになったが、10000にしても、3000くらいからセグフォになる問題に直面した。

しかし、Ubuntu環境では普通にセグフォは起きなかった。

sys.setrecursionlimit()について

Pythonの再帰回数の上限を確認・変更(sys.setrecursionlimitなど) | note.nkmk.me

この記事を参考にsys.setrecursionlimit()を使って、これの挙動を見ることで問題を解決しようとしました。

けど、これでもMacの環境ではなぜか3000ではセグフォになる。

解決

コンパイルにおけるバイナリファイルに問題があるかもしれない、ビルドの時に問題があるかもしれないという助言を受け、ビルドをする時、

$ CFLAGS="-g -O0" ./comfigure --prefix="インストール先のフォルダのパス"

としたのを

$ ./comfigure --prefix="インストール先のフォルダのパス"

として、最適化レベルの部分を消すと、上記の変更でうまく行くようになった。

結論

# ceval.c
#ifndef Py_DEFAULT_RECURSION_LIMIT
#define Py_DEFAULT_RECURSION_LIMIT 10000
#endif

 のように変更すれば、再帰上限を増やすことができた。

後、普通にsys.setrecursionlimit()を使ってもできます。