BBH
-Biz Branding Hub-
投稿日 : 
2019/12/17
更新日 : 
2019/12/17

【python】正規表現をコンパイルする方法とコンパイルすべきタイミングについて

pythonで正規表現を扱う際に、コンパイルする例を紹介します。
事前にコンパイルをしておくことで、その分のオーバーヘッドを短縮することができます。
例えば、ループ内で正規表現検索をする場合、毎回コンパイルするのと事前にコンパイルしておくのを比べると、後者の方が早いです。
ただし、単発で正規表現チェックをする場合は、コンパイルをしても全体の実行速度はそこまで早くなりません。

正規表現をコンパイルするサンプル

正規表現のコンパイル(python)

import re

# 正規表現をコンパイル
pattern = r'\[\d{1,}\]' 
re_pattern = re.compile(pattern)

# 変換前
val = '[12345]abcdefg'
print(val)

# 変換後
result = re_pattern.sub('', val)
print(result)

実行結果

[12345]abcdefg  # 変換前
abcdefg              # 変換後

正規表現をコンパイルすべきタイミングについて

記事冒頭でも少し触れていますが、単発で使用するような場合は、正規表現をコンパイルする必要はありません。
以下のような場合は、コンパイルしても1回しか使用されないので、性能の向上はほとんど見られません。

正規表現をコンパイルしなくてもよいケース

import re

# 正規表現をコンパイル
pattern = r'\[\d{1,}\]' 
re_pattern = re.compile(pattern)

# 正規表現で変換(1回しか使われない)
result = re_pattern.sub('', '[12345]abcdefg')
print(result)

一方、以下のようにループの中で何度も参照されるような場合は、コンパイルするメリットがあります。

正規表現をコンパイルすべきケース

# 正規表現のコンパイル実行
pattern = r'\[\d{1,}\]' 
re_pattern = re.compile(pattern)

# ループ
for(int i = 0; i < 100000; i++)
  # 正規表現で変換(ループ中で何回も使用される)
  result = re_pattern.sub('', '[12345]abcdefg')
  print(result)

具体的な性能向上については、以下のような検証結果があります。


実行速度の比較

・コンパイル無し
~$ for x in 1 10 100 1000 10000 100000 1000000; do python -m timeit -n $x -s 'import re' 're.match("[0-9]{3}-[0-9]{3}-[0-9]{4}", "123-123-1234")'; done
1 loops, best of 3: 3.1 usec per loop
10 loops, best of 3: 2.41 usec per loop
100 loops, best of 3: 2.24 usec per loop
1000 loops, best of 3: 2.21 usec per loop
10000 loops, best of 3: 2.23 usec per loop
100000 loops, best of 3: 2.24 usec per loop
1000000 loops, best of 3: 2.31 usec per loop

・コンパイルあり
~$ for x in 1 10 100 1000 10000 100000 1000000; do python -m timeit -n $x -s 'import re' 'r = re.compile("[0-9]{3}-[0-9]{3}-[0-9]{4}")' 'r.match("123-123-1234")'; done
1 loops, best of 3: 1.91 usec per loop
10 loops, best of 3: 0.691 usec per loop
100 loops, best of 3: 0.701 usec per loop
1000 loops, best of 3: 0.684 usec per loop
10000 loops, best of 3: 0.682 usec per loop
100000 loops, best of 3: 0.694 usec per loop
1000000 loops, best of 3: 0.702 usec per loop


従って、同じ正規表現をループなどで使い回す時は、コンパイルした方が実行速度は早くなるようです。

Profile

管理人プロフィール

都内でITエンジニアをやってます。
変遷:中規模SES→独立系SIer→Webサービス内製開発
使用技術はその時々でバラバラですが、C#、AWSが長いです。
どちらかと言うとバックエンドより開発が多かったです。
顧客との折衝や要件定義、マネジメント(10名弱程度)の経験あり。
最近はJava+SpringBootがメイン。

Recommend