문제

대량의 정적 정규식이 포함된 Python 파일을 가져올 때마다 CPU 주기는 문자열을 메모리의 대표 상태 머신으로 컴파일하는 데 사용됩니다.

a = re.compile("a.*b")
b = re.compile("c.*d")
...

질문:가져올 때마다 정규식 컴파일을 실행할 필요가 없도록 미리 컴파일된 방식으로 디스크의 캐시에 이러한 정규식을 저장할 수 있습니까?

객체를 피클링하면 단순히 다음 작업이 수행되어 어쨌든 컴파일이 발생합니다.

>>> import pickle
>>> import re
>>> x = re.compile(".*")
>>> pickle.dumps(x)
"cre\n_compile\np0\n(S'.*'\np1\nI0\ntp2\nRp3\n."

그리고 re 객체는 비정렬화됩니다:

>>> import marshal
>>> import re
>>> x = re.compile(".*")
>>> marshal.dumps(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: unmarshallable object
도움이 되었습니까?

해결책

가져올 때마다 정규식 컴파일을 실행할 필요가 없도록 미리 컴파일된 방식으로 디스크의 캐시에 이러한 정규식을 저장할 수 있습니까?

쉽지는 않습니다.C에 연결되는 사용자 정의 직렬 변환기를 작성해야 합니다. sre Python 정규식 엔진 구현.성능상의 이점은 필요한 시간과 노력보다 훨씬 더 큽니다.

먼저, 실제로 코드를 프로파일링했습니까?정규식 컴파일이 애플리케이션 런타임의 중요한 부분인지 의심됩니다.현재 실행에서 모듈을 처음 가져올 때만 컴파일된다는 점을 기억하세요. 그 이후에는 모듈과 해당 속성이 메모리에 캐시됩니다.

기본적으로 한 번 생성되고 여러 정규 표현식을 컴파일한 다음 종료되는 프로그램이 있는 경우 한 번의 호출로 여러 테스트를 수행하도록 리엔지니어링을 시도할 수 있습니다.그런 다음 위와 같이 정규식을 다시 사용할 수 있습니다.

마지막으로 정규식을 C 기반 상태 머신으로 컴파일한 다음 이를 확장 모듈과 연결할 수 있습니다.이는 유지 관리가 더 어려울 수 있지만 애플리케이션에서 정규식 컴파일을 완전히 제거합니다.

다른 팁

각 모듈은 가져오기 횟수에 관계없이 앱 수명 동안 한 번만 초기화됩니다.따라서 모듈의 전역 범위에서 표현식을 컴파일하면(예:함수에 있지 않음) 괜찮을 것입니다.

우선, 이것은 Python re 모듈의 명확한 제한 사항입니다.이로 인해 정규 표현식의 양과 크기가 합리적으로 제한됩니다.제한은 장기 실행 프로세스의 경우 더 크고 명령줄 애플리케이션과 같은 단기 프로세스의 경우 더 작습니다.

몇 년 전에 제가 본 적이 있는데, 컴파일 결과를 파헤쳐 피클한 다음 피클을 해제하고 재사용하는 것이 가능했습니다.문제는 sre.py 내부를 사용해야 하므로 다른 Python 버전에서는 작동하지 않을 수 있다는 것입니다.

내 도구 상자에 이런 종류의 기능이 있었으면 좋겠습니다.대신 사용할 수 있는 별도의 모듈이 있는지도 알고 싶습니다.

그만큼 선반 모듈이 제대로 작동하는 것 같습니다.


import re
import shelve
a_pattern = "a.*b"
b_pattern = "c.*d"
a = re.compile(a_pattern)
b = re.compile(b_pattern)

x = shelve.open('re_cache')
x[a_pattern] = a
x[b_pattern] = b
x.close()

# ...
x = shelve.open('re_cache')
a = x[a_pattern]
b = x[b_pattern]
x.close()

그런 다음 자동으로 캐싱을 처리하여 사용자에게 투명하게 되는 멋진 래퍼 클래스를 만들 수 있습니다.독자에게 남겨진 연습.

/usr/lib/python2.5/re.py를 열고 "def _compile"을 찾으세요.re.py의 내부 캐시 메커니즘을 찾을 수 있습니다.

각 정규식(또는 정규식 그룹)을 별도의 파일에 배치한 다음 imp 모듈을 사용하여 필요한 파일을 동적으로 가져올 수 있습니다.나는 그것이 매우 잘 확장되는지 의심하지만 그것이 당신에게 필요한 것일 수 있습니다.

흠,

선반은 피클을 사용하지 않습니까?

어쨌든 나는 이전 답변에 동의합니다.모듈은 한 번만 처리되므로 정규 표현식을 컴파일하는 것이 앱 병목 현상이 될지는 의심스럽습니다.그리고 Python re 모듈은 C로 코딩되었기 때문에 매우 빠릅니다 :-)

하지만 좋은 소식은 Python에 좋은 커뮤니티가 있다는 것입니다. 따라서 현재 필요한 것을 해킹하고 있는 누군가를 찾을 수 있을 것이라고 확신합니다.

5초간 구글링해서 찾았습니다. http://home.gna.org/oomadness/en/cerealizer/index.html.

그것이 될지는 모르겠지만 그렇지 않다면 연구에 행운이 있기를 바랍니다 :-)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top