2014年10月10日金曜日

pythonで再帰処理をする際はlimitに要注意なので再帰処理を使わずに書いてみたよ的なお話

  • このエントリーをはてなブックマークに追加

タイトルの通り、pythonで再帰処理を行う際には上限があるので要注意的なお話。
ざくっと例を示して書いた方が早いので今回は前置きは無しにしてそのお話をば。

とあるディレクトリ以下のファイルを全て抽出して、配列に入れるという感じのプログラム。

■失敗例

def get_all_files_in_dir(_paths):
  files = []

  for file_path in _paths:
    if not os.path.isdir(file_path):
      files.append(os.path.abspath(file_path))
    else:
      list = glob.glob(file_path + "/*")
      for file in list:
        if os.path.isdir(file):
          files.extend(get_all_files_in_dir(file))
        else:
          files.append(os.path.abspath(file))

  return files
これだとファイル数によってはRuntimeError: maximum recursion depth exceededと出てしまい、
処理が途中で止まってしまう。
try〜exceptみたいな感じでやれば多分大丈夫なんだろうけれど、
それだとファイルを全部抽出することが出来なくて意味がないので再帰処理を使わずにやろうかと。

成功例
def dir_is_exists_in_array(_ary):
  flg = 0

  for s in _ary:
    if os.path.isdir(s):
      flg = 1

  return flg

def get_subdir_files(_ary):
  files = _ary

  for f in _ary:
    if os.path.isdir(f):
      subfiles = glob.glob(f + "/*")
      files.extend(subfiles)
      files.remove(f)

  return files

def get_all_files_in_dir(_paths):
  files = []

  while dir_is_exists_in_array(_paths):
    _paths = get_subdir_files(_paths)

    for file_path in _paths:
      files.append(os.path.abspath(file_path))

  return files
とりあえずこんな感じ。
ディレクトリがあるならばwhile文みたいな感じにしておき、
そのwhile文の中でglobしてファイルリストを出しって感じの処理。
再帰処理をばらすとなるとこんな感じになって中々に面倒だなぁと思った。

ちなみにこんな方法で再帰処理の上限を緩和することができる。
sys.setrecursionlimit(10000)
通常は1000回らしいんだけどこれで10000回まで計算することができるが、
本当にどんな状況でも出来るのか?ってなると微妙なところだから再帰処理は出来るだけやめておきましょうみたいな。

けどまぁこれでちゃんとエラーが出ずに最後までファイルを検索出来るのでいいんじゃないかと。
特にsublimeのプラグインとして使う場合に、一番下まで抽出したいとかっていうこともあるだろうみたいな。

Adsense