웹브라우저로 python 실행하기

singleheart·2023년 8월 6일
1
post-thumbnail

Python 코드를 웹에서 직접 실행할 수 있으면 편할 것입니다. PHP나 Django에서 파이썬 스크립트 파일을 실행하는 방법이 아니라, JavaScript처럼 HTML 파일에 직접 파이썬 스크립트를 포함시켜서 실행하는 방법을 설명합니다. 이를 위한 프로젝트로 Pyodide가 있는데요, PyScript로 훨씬 간편하게 할 수 있습니다.

Hello, World

아래 코드를 html로 저장하고 웹브라우저에서 열어 봅시다.

<html>
  <head>
    <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
    <script defer src="https://pyscript.net/latest/pyscript.js"></script>
  </head>
  <body> 
    <py-script>
      print('Hello, World!')
    </py-script>
  </body>
</html>

화면 왼쪽에 Hello, World!라는 문구가 나타납니다. 

print문이 작동했다는 사실에 살짝 놀랄 수도 있습니다만, <body> 태그 안에 그냥 문자열을 넣으면 더 간단한데 이런 코드가 무슨 의미가 있냐고 생각할 수도 있습니다. 이 코드만 보면 파이썬인지 다른 언어인지도 확실치 않습니다. 그래서 계산을 하는 예시를 보겠습니다.

간단한 계산

<html>
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
    <script defer src="https://pyscript.net/latest/pyscript.js"></script>
  </head>
  <body>
      <py-script>
print("π를 계산해 봅시다:")
def wallis(n):
    pi = 2
    for i in range(1,n):
        pi *= 4 * i ** 2 / (4 * i ** 2 - 1)
    return pi

pi = wallis(100000)
s = f"π는 대략 {pi:.3f}입니다."
print(s)
      </py-script>
  </body>
</html>

드디어 익숙한 파이썬 코드가 등장했습니다. 월리스 공식을 이용하여 π의 근사값을 계산합니다. 3.142라는 결과가 아쉽다면 n을 늘리고 출력할 부동소수점의 길이를 늘려주면 됩니다. 
이제 py-script 태그만 있으면 파이썬 코드를 돌릴 수 있습니다. 그런데 웹페이지에서 print만 쓸 수는 없겠지요. 자바스크립트처럼 웹페이지의 구성요소와 상호작용할 수 있을까요?

웹페이지 요소 변경

<html>
    <head>
      <meta charset="utf-8">      
      <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
      <script defer src="https://pyscript.net/latest/pyscript.js"></script>
      <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
    </head>

  <body>
    <b><p>오늘 날짜는 <u><label id='today'></label></u></p></b>
    <br>
    <div id="pi" class=" -primary"></div>
    <py-script>
import datetime as dt
pyscript.write('today', dt.date.today().strftime('%A %B %d, %Y'))

def wallis(n):
    pi = 2
    for i in range(1,n):
        pi *= 4 * i ** 2 / (4 * i ** 2 - 1)
    return pi

pi = wallis(100000)
pyscript.write('pi', f'π는 대략 {pi:.3f}입니다.')
    </py-script>
  </body>
</html>


페이지를 처음 열 때에는 "오늘 날짜는"만 보이고 잠시 후 <label>이 업데이트되는 것을 확인할 수 있습니다. 코드를 보면 import가 작동한다는 사실도 확인할 수 있습니다. 혹시 기본이 아닌 패키지도 불러올 수 있을까요? 그렇다면 정말 좋을 텐데요.

numpy, matplotlib 불러오기

<html>
  <head>
    <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
    <script defer src="https://pyscript.net/latest/pyscript.js">
    </script>
  </head>
  <body>
    <h1>Let's plot random numbers</h1>
    <div id="plot"></div>
    <py-config>
      packages = ["matplotlib", "pandas"]
    </py-config>
    <py-script>
import matplotlib.pyplot as plt
import numpy as np

x = np.random.randn(1000)
y = np.random.randn(1000)

fig, ax = plt.subplots()
ax.scatter(x, y)
display(fig, target="plot")
    </py-script>
  </body>
</html>

numpy, matplotlib 등도 불러와서 그림을 그려 줍니다. 이미 파이썬을 개발하던 분들이면 이 부분에서 살짝 놀랄 수도 있습니다. 이 예제를 실행하는 http 서버에 이 패키지들을 설치 안 한 상태에서도 되거든요. 

그렇다면 pypi에 없는 whl은 될까요? <py-config> 에 whl 파일의 경로를 적어 주면 됩니다. 아래에 예시가 있습니다:

<py-config>
  packages = ["./static/wheels/travertino-0.1.3-py3-none-any.whl"]
</py-config>

.py 호출

HTML 하나에 파이썬 코드 전체를 적을 수 없는 경우도 있을 텐데요, 다행히 .py 파일도 불러올 수 있습니다. <py-config>paths 항목에 적어 주면 됩니다. 

아래처럼 data.py 파일을 먼저 준비하고요,

import numpy as np

def make_x_and_y(n):
    x = np.random.randn(n)
    y = np.random.randn(n)
    return x, y

HTML 파일은 아래와 같습니다.

<html>
    <head>
      <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
      <script defer src="https://pyscript.net/latest/pyscript.js"></script>
    </head>

  <body>
    <h1>Let's plot random numbers</h1>
    <div id="plot"></div>
    <py-config>
      packages = ["matplotlib", "pandas"]
      
      [[fetch]]
      files = ["./data.py"]
    </py-config>    
    <py-script output="plot">
import matplotlib.pyplot as plt
from data import make_x_and_y

x, y = make_x_and_y(n=1000)

fig, ax = plt.subplots()
ax.scatter(x, y)
display(fig, target="plot")
    </py-script>
  </body>
</html>

결과는 앞의 플롯 그리기와 같습니다. 다만, 이 예제는 이전에 설명한 다른 예제와 달리 로컬에서 실행하면 Cross origin requests are only supported for HTTP 등의 에러가 발생할 수 있습니다. 웹서버를 준비하고 서버에서 실행해주세요. 참고로 파이썬에서 http 서버를 띄우기 가장 간단한 방법은 python -m http.server 포트번호 --bind IP주소로 띄우는 것입니다. 상용 성능은 아니지만 디버깅용으로 편리합니다. 이렇게 띄운 뒤에 IP주소:포트번호로 웹브라우저에서 접속하면 실행한 디렉토리가 보일 것입니다. 여기서 html 파일을 선택해서 보면 됩니다.

지금까지 PyScript에 대해서 알아보았습니다. 그런데 pyscript.js, css를 일일이 서버에서 받아오고 있었습니다. 자신의 서버에서 직접 제공할 수 있을까요?

PyScript 직접 설치

PyScript 홈페이지에서 다운로드하고 압축을 풀면 Install이 필요 없다는 설명과 달리 바로 사용할 수 있는 상태가 아닙니다. (물론 https://pyscript.net/latest로 연결하면 됩니다만, 이는 앞으로 바뀔 수 있습니다. 실제로 이 글을 처음 작성할 때에는 주소가 alpha였는데 지금은 latest로 바뀌었습니다) 따라서 빌드가 필요합니다. 

우선 node가 없으면 설치해야 하고요, npm으로 빌드합니다. 빌드 방법은 pyscriptjs/README.md에 적혀 있으니 그대로 따라하면 됩니다. 빌드가 완료되면 pyscriptjs/examples/build에 pyscript.js, css 파일이 생기니 이를 링크해서 쓰면 됩니다. pyscriptjs/examples에는 다양한 예제가 있는데요, build 디렉토리가 pyscriptjs/build라고 가정하고 작성한 코드이므로 build 디렉토리를 옮기고 여는 것이 좋습니다.

※ 모든 예제의 원본은 https://github.com/pyscript/pyscript/blob/main/GETTING-STARTED.md 페이지에 있습니다.

profile
개발자

1개의 댓글

comment-user-thumbnail
2023년 8월 6일

좋은 글이네요. 공유해주셔서 감사합니다.

답글 달기