Closed kwonmha closed 4 years ago
문제점을 파악하여 말씀드립니다.
Util.initialize()
코드상에서
start_jvm()
이후,
check_jvm()
을 하는데요,
check_jvm()
은
class_of('java.lang.String')('123')
코드로
Java String class를 만들고 JavaClass.__call()__
까지 실행합니다.
그 후, finalize()
를 해도, 'java.lang.String
이 _CLASS_DIC
에 남아 있어서
새로운 initialize()
과정에서
class_of('java.lang.String')('123')
코드를 실행하면
class_of()
의 level = level.__getattr__()
를 실행하면서
__init__
하고, __call__
을 하는 게 아니라,
이미 'java.lang.String'이 '_CLASS_DIC' 안에 남아있기 때문에 바로 리턴이 되고, __call__
이 실행됩니다.
이 JavaClass 인스턴스는 이전 jvm을 finalize()
하면서 is_connected = False
가 된 GatewayClient
를 갖고 있습니다.
그래서
def check_jvm():
class_of('java.lang.String')('123')
del _CLASS_DIC['java.lang.String']
로 수정해봤습니다.
완벽한 해결책은 아닌 것 같아요. 다른 부분들에서도 문제가 생겨서 좀 더 알아보고 있습니다.
finalize -> initialize를 하려는 이유는, 10기가 정도 되는 코퍼스를 대상으로 문장분리 작업을 하고 있는데, 일정한 위치에서 문장 분리가 멈추는 현상이 일어나기 때문입니다. 한 번에 처리하는 텍스트 양을 바꾸면 또 전혀 상관없는 위치에서 문장 분리가 멈춰 버립니다. 코드는 대략 아래와 같습니다.
initialize(java_options="-Xmx10g -Xms10g -Dfile.encoding=utf-8", HNN='2.0.3')
splitter = SentenceSplitter('hnn')
while i < len(corpus):
corpus_segment = corpus[i: min(i+char_count, len(corpus))]
sentences.extend(splitter(corpus_segment))
그래서 재시작하면 멈추는 현상이 안 일어날 것 같아 재시작을 해보려고 했는데, 그것도 여의치 않네요.
위에 말씀드린 Java.lang.String
관련 문제가 다른 클래스들에서도 일어납니다. 그래서 shutdown_jvm()
을 아래와 같이 수정했습니다.
def shutdown_jvm():
global GATEWAY
global _CLASS_DIC
GATEWAY.shutdown()
GATEWAY = None
_CLASS_DIC = {}
return is_jvm_running()
한 프로세스 안에서 jvm을 다시 시작하면 initialize()
의 _resolve_artifacts_modified()
를 실행할 때 이미 필요한 라이브러리가 이미 있다고 생각해서 그런지 다시 다운받지 않습니다. 그래서 리턴값을 받는 down_list
가 비어 있고, 결과적으로 start_jvm(java_options, classpaths)
의 classpaths
가 없습니다. 그래서 필요한 SentenceSplitter()를 다시 생성하지 못합니다. 일단 저는 글로벌 변수 하나를 만들어서 해결했습니다.
def initialize():
...
down_list.sort(key=lambda a: a.repos.uri)
if len(down_list) == 0:
global _DOWN_LIST
down_list = _DOWN_LIST
else:
_DOWN_LIST = down_list
for artifact in down_list:
...
@kwonmha 인사가 늦었습니다. 말씀하신 대로 재초기화 관련 코드에 문제가 있습니다. 알려주신 방법으로 임시 조치가 가능하지만, 더 좋은 방법이 있어 수정하고 push하였으니 변경사항을 확인하실 수 있을 것 같습니다. 지금은 몇 가지 더 고칠 사항이 있어서, 새 버전 업로드 때에 다시 알려드리겠습니다.
네 감사합니다.
KoalaNLP PyPi 패키지 2.1.3부터 적용되었습니다. 감사합니다.
finalize() 후에, 다시 initialize()하려고 하는데, 아래처럼 에러가 납니다.
왜 그런 건지 혹시 알 수 있을까요?
그리고 아래 코드 링크처럼 exception 메세지에 보니, koalanlp.Util.done()을 하라고 하는데, done()이란 함수가 빠진 건가요, 아니면 finalize()를 의미하는 건가요?
https://github.com/koalanlp/python-support/blob/20cd7ded80fb79a4606b2fd830d9b5a7b062ad27/koalanlp/Util.py#L202