본문 바로가기

개발하자

주피터 노트북 내부 플라스크 서버 디버그

반응형

주피터 노트북 내부 플라스크 서버 디버그

나는 데모를 위해 주피터 노트북 안에 있는 작은 플라스크 서버를 디버그하고 싶다.

나는 최신 우분투와 파이썬 2에서 가상 엔브이를 만들었다 (파이썬 3이 있는 맥에서도 이 오류가 발생한다), 핍 인스톨 플라스크 주피터.

그러나 "Hello World" 스크립트로 셀을 만들 때 노트북 내부에서 실행되지 않습니다.

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run(debug=True,port=1234)
File "/home/***/test/local/lib/python2.7/site-packages/ipykernel/kernelapp.py",
line 177, in _bind_socket 
    s.bind("tcp://%s:%i" % (self.ip, port))   
File "zmq/backend/cython/socket.pyx", line 495, in
  zmq.backend.cython.socket.Socket.bind
 (zmq/backend/cython/socket.c:5653)   
File> "zmq/backend/cython/checkrc.pxd", line 25, in
  zmq.backend.cython.checkrc._check_rc
 (zmq/backend/cython/socket.c:10014)
     raise ZMQError(errno) ZMQError: Address already in use

NB – 포트 번호가 실패할 때마다 변경합니다.

네, 독립 실행형 스크립트로 실행됩니다.

업데이트:

(debug=True)가 없으면 괜찮습니다.




주피터와 플라스크를 설치했고 당신의 원래 코드가 작동합니다.


개체는 서버가 아닌 WSGI 응용 프로그램입니다. 플라스크는 셸을 호출하면 Werkzeug의 개발 서버를 서버로 사용합니다. 새 WSGI 서버를 만든 다음 응용프로그램을 매개변수로 에 전달합니다. 수동으로 시도해 볼 수도 있습니다:

from werkzeug.wrappers import Request, Response
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 9000, app)

내부적으로 전화를 걸었으니 여기서 차이가 없을 겁니다.




방법은 플라스크 서버를 별도의 스레드에서 실행하는 것입니다. 이 코드는 데이터 공급자 등록을 허용한다. 주요 특징은

  • 서버에 사용 가능한 포트를 찾습니다. 서로 다른 노트북에서 서버 인스턴스를 여러 개 실행하면 동일한 포트를 두고 경쟁하게 됩니다.

  • 이 기능은 서버의 URL을 반환하므로 필요한 모든 용도로 사용할 수 있습니다.

  • 서버는 주문형으로 시작됩니다(첫 번째 데이터 공급자가 등록될 때)

  • 패키지에서 데코레이터를 추가했어요. 그렇지 않으면 노트북 내에서 API 양식을 호출할 수 없습니다.

  • 이 코드에서는 서버를 정지시킬 방법이 없습니다...

  • 그 코드는 타이핑과 파이썬을 사용한다.

  • 현재로서는 제대로 된 오류 처리가 없습니다

import socket
import threading
import uuid
from typing import Any, Callable, cast, Optional

from flask import Flask, abort, jsonify
from flask_cors import cross_origin
from werkzeug.serving import run_simple

app = Flask('DataServer')


@app.route('/data/<id>')
@cross_origin()
def data(id: str) -> Any:
    func = _data.get(id)
    if not func:
        abort(400)
    return jsonify(func())


_data = {}

_port: int = 0


def register_data(f: Callable[[], Any], id: Optional[str] = None) -> str:
    """Sets a callback for data and returns a URL"""
    _start_sever()
    id = id or str(uuid.uuid4())
    _data[id] = f
    return f'http://localhost:{_port}/data/{id}'


def _init_port() -> int:
    """Creates a random free port."""
    # see https://stackoverflow.com/a/5089963/2297345
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost', 0))

    port = sock.getsockname()[1]
    sock.close()
    return cast(int, port)


def _start_sever() -> None:
    """Starts a flask server in the background."""
    global _port
    if _port:
        return
    _port = _init_port()
    thread = threading.Thread(target=lambda: run_simple('localhost', _port, app))
    thread.start()



이 질문은 오래 전에 제기된 것이지만, 나는 또 하나의 제안을 생각해낸다:

다음 코드는 PyCharm이 플라스크 콘솔을 시작하는 방법에서 가져온 것입니다.

import sys
from flask.cli import ScriptInfo
app = None
locals().update(ScriptInfo(create_app=None).load_app().make_shell_context())
print("Python %s on %s\nApp: %s [%s]\nInstance: %s" % (sys.version, sys.platform, app.import_name, app.env, app.instance_path))

이제 플라스크 문서에 설명된 모든 것을 액세스하고 사용할 수 있습니다


반응형