안녕하세요?파이썬아래아한글에LaTeX수식삽입하거나수식을LaTeX로추출하는방법클리앙
(속없이) 파이썬-아래아한글 자동화를 공부중인 일코입니다.
저는 최근에 IT 프리랜서를 그만두고
안양 소재 (합사 위주로 도는)
토목 관련 엔지니어링 회사에 취업해서 일하고 있습니다.
취업 직전까지 이를 갈면서
개발해 오던 파이썬 모듈이 하나 있었는데,
pyhwpx라고, 아래아한글 자동화를 간편하게 해주는
일종의 "유용한 함수모음" 같은 모듈입니다.
합사 일을 하면 느슨한 기간도 있지만,
프로젝트 마감이 가까워지거나, 일정이 꼬인다거나 하면
빡세게 야근도 하고 주7일 일하는 기간도 생기거든요.
그래서 개발에 많은 시간을 쏟기는 어렵지만
자기 전이나, 주말에 몰아서 pyhwpx를 조금씩 보완해 가는 중입니다.
오늘 소개해드릴 유용한 기능은
LaTeX 문자열을 아래아한글로 가져오거나,
아래아한글 수식을 LaTeX 문자열로 내보내는 기능입니다.
LaTeX문법이랑 한/글 수식 문법은
대체로 비슷하면서도 미묘한 차이가 있어서
수작업으로 LaTeX 수식을 hwp에 넣거나,
hwp 수식을 LaTeX로 추출하는 과정이
그리 단순하지만은 않거든요...
혹여 그런 작업 때문에 시간에 쫓기는 분들을 위해
파이썬 코드를 하나 공유해봅니다.
하여튼 이 글의 주제는
아래아한글 수식을 LaTeX 문자열로 변환하거나,
반대로 LaTeX 문자열을 아래아한글 수식으로 생성하는
파이썬 코드 공유입니다.
파이썬을 써오신 분들은 하단의 "본론"부터 읽으셔도 괜찮습니다.
준비작업
(파이썬과 아래아한글이 설치된 상태에서)
먼저 설치해야 할 모듈이 두 개 있습니다.
pyhwpx라는 아래아한글 프로그램을 조작하는 모듈과
py-asciimath라는 수식변환 모듈입니다.
커맨드프롬프트에서 `pip install pyhwpx py-asciimath`라는 명령어로 설치하실 수 있습니다.
설치가 완료되었으면 파이썬 코드를 작성하고 실행할 수 있는 에디터를 열어줍시다.
저는 주피터노트북을 사용하겠습니다.
주피터노트북도 `pip install jupyter`로 간편하게 설치하실 수 있습니다.
주피터가 설치되었으면
`jupyter notebook`을 실행합니다. (그러면 잠시 후 브라우저가 열리고 주피터 탐색기 화면이 뜹니다.)
우측 상단의 "New - Notebook"을 순서대로 클릭하여
새 노트북 파일을 엽니다.
(ChatGPT와 채팅하듯이, 파이썬 코드를 조금씩 넣고 Shift-Enter를 누르면 코드가 실행됩니다.)
이제 코드를 실행할 수 있는 프롬프트가 깜빡깜빡하는 상태입니다.
아래 두 줄 코드를 복사해서 주피터에 붙여넣거나,
직접 타이핑한 후"Shift-Enter"를 눌러 실행해보겠습니다.
from pyhwpx import Hwphwp = Hwp()
잠시 기다리면 아래아한글 창이 하나 생깁니다.
(아래아한글 창을 하나 열어놓고 위 코드를 실행해도 됩니다.)
이어서 아무 수식이나 하나 직접 삽입해봅시다.
저는 "입력 - 수식 - 기타공식"에서 2차방정식 근의 공식)을 삽입하겠습니다.
직접 입력하지 않고 아래 코드를 실행하셔도 됩니다.
(동일한 동작을 합니다.)
pset = hwp.HParameterSet.HEqEdithwp.HAction.GetDefault("EquationCreate", pset.HSet)pset.string = "x= { -b± sqrt { b ^{ 2} -4ac}} over { 2a}" pset.BaseUnit = 3000hwp.HAction.Execute("EquationCreate", pset.HSet)
수식이 하나 삽입되었습니다. (다른 수식을 넣으셔도 무방합니다.)
이제
수식을 LaTeX로 내보내거나, LaTeX수식을 한/글로 가져오기 위한 모든 준비작업을 마쳤습니다.
(벌써 고되다는 느낌이 올 수 있는데요. 사실 다 끝났습니다.)
본 론
자, 지금 우리 PC에는 주피터노트북,
그리고 아무개 수식만 하나 들어있는 한/글 문서가 하나 열려 있는 상태입니다.
아래아한글 수식을 LaTeX로 변환하거나 가져오는 코드는 제법 간단합니다.
그런데 딱 한번만 우리가 먼저 작업해야 할 게 있습니다.
py-asciimath라는 모듈이 윈도우용으로 만들어져 있지 않아서
코드를 아주 조금 수정해줘야 합니다.
(우리가 진행하는 튜토리얼 중에서 가장 번거로운 일일 겁니다.)
우선 py-asciimath 모듈이 설치되어 있는 폴더로 찾아갑니다.
제 경우에는 `C:\Program Files\Python312\Lib\site-packages\py_asciimath`에 설치가 되었네요.
버전이 다르거나, 가상환경이라는 걸 사용하시는 분들은 적절한 폴더를 찾아가보시기 바랍니다.
그 안에 __init__.py 라는 파일이 하나 있는데요.
그 파일을 메모장 같은 걸로 열어봅시다.
기존 내용은 아마 아래와 같을 겁니다.
import osPROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))__version__ = "0.3.0"
이 내용을 아래 코드로 덮어씌워주세요.
import platformimport osif (platform.system() == 'Windows'): PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__)).replace('\\', '/')else: PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))__version__ = "0.3.0"
저장하신 뒤 주피터노트북 화면 상단에서 동그란 화살표를 클릭해서 노트북을 재시작합니다.
자 이제 준비 끝입니다!!!!!!!!!!!!!! (준비라지만 가장 빡센 작업이었어요ㅜ)
① 이 수식을 LaTeX로 추출하는 코드부터 알아보겠습니다.
아래 코드를 복사해서 주피터에 붙여넣고 실행(Shift-Enter)해봅시다.
(보이지 않는 특수문자가 같이 복사될 수 있으니, 아래 코드 중 제일 위 빈 줄은 빼고 복사해주세요~)
from py_asciimath.translator.translator import MathML2Texfrom pyhwpx import Hwphwp = Hwp()hwp.SelectCtrlFront()mml_path = "eq.mml"hwp.export_mathml(mml_path)mathml2tex = MathML2Tex()with open(mml_path) as f: mml_eq = f.read()tex_eq = mathml2tex.translate(mml_eq, network=False, from_file=False)print(tex_eq)
(특정 환경에서는 오류가 날 수 있는데요. 10번 라인의 `network=False`를 `network=True`로 수정해보시면 잘 될 거예요.)
빨간 부분은 모두 무시하시고,
가장 아래에 출력된 라인만 보면
우리가 원했던, LaTeX 수식 문자열라는 걸 알 수 있습니다.
다행히 주피터노트북 안에서도 LaTeX 수식을 확인할 수 있거든요?
빈 셀에 붙여넣기하고, 수식 모양을 확인해봅시다.
출력된 수식을 복사해서 가장 마지막 셀(코드입력칸)에 붙여넣기하신 후에
"Esc, M, Shift-Enter"를 차례대로 눌러주면 마크다운이 활성화되어 수식이 나타납니다.
음, 그럴싸하게 변환이 되기는 하네요. 그쵸?
아래처럼 반복문을 사용하면,
문서의 모든 수식을 LaTeX 문자열 리스트로 만들 수도 있습니다.
from py_asciimath.translator.translator import MathML2Texfrom pyhwpx import Hwptex_list = []hwp = Hwp()for ctrl in hwp.ctrl_list: if ctrl.UserDesc == "수식": mml_path = "eq.mml" hwp.select_ctrl(ctrl) hwp.export_mathml(mml_path) mathml2tex = MathML2Tex() with open(mml_path) as f: mml_eq = f.read() tex_eq = mathml2tex.translate(mml_eq, network=True, from_file=False) tex_list.append(tex_eq)print(tex_list)
② 이제 LaTeX 수식을 한/글에 삽입하는 과정도 한 번 보여드리겠습니다.
제가 지금... 분량조절에 실패하고 있는지,
글이 너무 늘어지는 느낌이 들어요ㅜ
간결하게 코드와 실행결과만 공유드려봅니다.
(붙여넣기 하고 실행만 하시면 돼요! 궁금하시거나 오류가 발생하면 댓글이나 메일로 알려주세요! 메일주소는 하단에.)
py_asciimath 외에도 훌륭한 LaTeX2MathML 변환모듈이 있는데요.
바로 latex2mathml입니다. 얘를 활용하는 예시로 보여드리겠습니다.
이번엔 주피터노트북 빈 셀에
%pip install latex2mathml
이라고 입력하고 실행(Shift-Enter)해봅시다.
설치가 완료되었습니다. 편리하네요ㅎ
마지막으로 아래 코드를 빈 셀에 붙여넣고 실행해봅시다.
eq_list의 문자열들은 외국 LaTeX 온라인변환 사이트에서 가져온 예시 수식들인데,
이것들을 가지고, 한/글 수식으로 얼마나 잘 변환되는지 한 번 테스트해볼 거예요.
from latex2mathml import converterfrom pyhwpx import Hwpeq_list = [ r"\displaystyle x = \frac{ - b \pm \displaystyle\sqrt { b^2 - 4ac} }{ 2a}\ { \text{ when}}\ { ax^2 + bx + c = 0}", r"\displaystyle \sin(x) = \displaystyle\sum_{ n=0}^\infty \frac{ (-1)^n}{ (2n+1)!}\ x^{ 2n+1} = x - \frac{ x^3}{ 3!} + \frac{ x^5}{ 5!}- \frac{ x^7}{ 7!}\ ...", r"\displaystyle P_\lambda = \frac{ 2 \pi h c^2}{ \lambda^5 \left(e^{ \left(\frac{ h c}{ \lambda k T}\right)} - 1\right)}", r"\displaystyle I(v,T) = \frac{ 2 \, h v^{ 3}}{ { \left(e^{ \left(\frac{ h v}{ k T}\right)} - 1\right)} c^{ 2}}", r"\displaystyle \Delta x \Delta p \geq \frac{ 1}{ 2} \hbar", r"\displaystyle pdf = \frac{ 1}{ \sqrt{ 2 \pi \sigma^2}}\ e^{ -\frac{ (x-\mu)^2}{ 2 \sigma^2}}", r"\displaystyle cdf(a,b,\mu,\sigma) = \displaystyle\frac{ 1}{ \sqrt{ 2 \pi \sigma^2}} \displaystyle\int_a^b e^{ -\frac{ (x-\mu)^2}{ 2 \sigma^2}}\ dx",]hwp = Hwp()for eq in eq_list: # MathML 변환 mml = converter.convert(eq) with open("m_txt.mml", "w") as f: f.write(mml) hwp.import_mathml("m_txt.mml") hwp.BreakLine()
실행결과는 아래와 같습니다.
(데스크탑에서는 움짤이 재생되는데, 모바일에서는 멈춰 있네요ㅜ)
하여튼 짜잔~이라기엔 수식변환 결과가 조금... 글쵸?
그래도 괄호순서나 줄바꿈 정도만 조금 수정하면
제법 쓸만하지 않을까요?ㅎ
마치며
어떠셨나요?
사실 저는 처음에 이런 게 된다는 게 마냥 신기하기만 하고,
조금만 다듬으면 꽤 유용하겠다 싶어서,
막상 이것저것 관심을 갖고 공부해보니까......
아직 파이썬 진영에 LaTeX 관련 모듈들이
부족한 부분들이 많기는 한 것 같아요ㅜ
(제가 제대로 검색을 못 했거나, 제 욕심이 과한 건가 싶기도 하고요...)
특히 한/글 수식으로 변환하거나 내보내는 기능을
파이썬으로 제대로 만들어보고 싶은데
우선 저부터 코딩역량이 뛰어난 편이 아니고,
LaTeX 변환 모듈들도 여러 개 써봤는데,
하여튼 다 뭔가 하나씩 부족한 느낌이에요...
어쩌면 이런 자료도
수많은 삽질 끝에 얻었던 선배의 결론 아닌가 싶고요.
주절주절 글이 길었습니다.
아직은 많이 부족하지만 틈틈이 계속 다듬어서
누군가에게 도움이 될 수 있을 만큼 그럴싸한 기능들이 구현되면
그 때 다시 한 번 더 공유하겠습니다.
pyhwpx는
아래아한글을 손쉽게 자동화하는 파이썬 모듈,
pyhwpx에 대한 개발일지는
블로그에 종종 작성하고 있어요. (네이버블로그는 긴 gif파일을 최적화해준다는 장점이 있네요ㅎ)
[pyhwpx기초] 공번정리(BH-1을 BH-001로 변경)하는 방법
아직 문서화를 해놓지 못한 상태여서
설명서나 튜토리얼이랄 게 블로그 외엔 마땅히 없는데
조만간 다른 모듈들처럼 "공식문서"라는 것도 한 번 만들어서 공유할 예정입니다.
혹시 미리 써보시다가 어렵거나 오류가 발생하면
자유롭게 메일로 남겨주세요.
제 메일주소는 martinii.fun@지메일입니다.
주절주절 긴 글, 끝까지 읽어주셔서 감사합니다.
편안한 밤, 행복한 하루 되세요!!