✨ Flask

Haks.·2024년 12월 30일
0

How to use

목록 보기
11/32

Flask

  • RestAPI : HTTP 프로토콜을 사용하여 인터넷을 통해 클라이언트와 서버 간에 통신하는 것
    RestAPI 는 HTTP의 특성과 메서드를 활용하여 요청과 응답을 주고 받는다.

📖 Flask

마이크로 프레임워크

  • 웹 개발 최소 기능 제공, RESTful 요청 처리, 유니코드 기반, 필요한 부분은 추가해서 확장 가능
  • __name__ 이란?, __name__ 이라는 변수는 모듈의 이름이 저장됨
    • 실행하는 코드에서 main이 들어감
    • 예를 들어 같은 폴더안에 있는 test.py 라는 파일을 start 파일안에서 모듈처럼 사용하 print(name)을 하면 현재 파일의 name 인 main 과 test 라는 파일명이 출력된다
    • 즉 해당 파일이 메인으로 실행되는 폴더면 main 아니면 임포트 된 파일명출력
    • 함수 같은 것이 아닌 원래는 출력됨 그래서 if __name__ == '__main__': 으로 함수 코드를 작성해서 그 함수가 메인이라는 이름을 가질때만 해당 기능을 실험할 수 있음
    • 모듈로서 실행할때는 기능이 작동하지 않게 하는 것
  • 시작점(entry point) : c,java 같은 언어는 코드를 시작하는 시작점(enty point)를 가지고 있음 ex) int main()
  • 파이썬과 시작점(entry point)
    • 파이썬은 스크립트 언어
    • 스크립트 언어는 전통적으로 시작점없이 스크립트 코드를 바로 실행함
from flask import Flask

# 구분하기 위해 이름을 매겨놓은 것임 __name__ 으로
app = Flask(__name__) # 만들 객체 이름, 일반적으로 프레임워크를 만들떄 사용하는 가이드, 일반적으로 이렇게 만듬 웹서비스

__name__ # 파이썬에서 제공하는 문법
app # 현재 메인이니까 main으로 나옴

📌 라우팅


  • 적절한 목적지를 찾아주는 기능
  • URL을 해당 URL 에 맞는 기능과 연결해 줌
    • 주소/hello (주소 서버에서 hello 이라는 목적지에 맞는 함수를 호출해 줌)
@app.route("/hello") # 여기 경로로 접속하면 바로밑의 함수를 호출하도록 만들어 놓은 것, 데코레이터
def hello():
    return "<h1>Hello World!</h1>"
  • 메인 모듈로 실행될 떄 flask 웹 서버 구동 (플라스크에서는 task 를 쉽게 해주기 위해서 자체적으로 웹서버 기능을 제공하고 있음)
    • 서버로 구동한 IP와 포트를 옵션으로 넣어 줄 수 있음
    • app.run() 함수로 서버 구동 가능(host, port, debug) 주로 사용 인자로
    • run(host=None, port=None, debug=True) 이런식 경로 설정, host 주소, port 번호
  • Web Server 와 WAS 프레임워크
    • 웹서버는 정적인 HTML 페이지를 반환한다.
    • 웹서버가 동적으로 데이터를 반환하도록 하기 위해서는, WAS 프레임워크가 필요하다. (Django,Spring,nods.js, rails...)

🧑‍💻 실습

from flask import Flask

app = Flask(__name__) # 플래스크 객체 생성
@app.route("/hello") # 핼로우라고 접속하면 
def test():
    return "<h1>Hello Flask!</h1>" # 이 내용이 되도록 웹페이지로 리턴되도록 구성, <h1> 표시가 확대 
@app.route('/') # 기본 화면
def main():
    return 'main'

host_addr = "0.0.0.0" # 보통 자기 주소 는 0.0.0.0 or localhost or 127.0.0.1
port_num = "8080" # 보통 8080 번을 test로 자주 사용함

if __name__ == "__main__" : 
    app.run(host=host_addr, port = port_num) # 밑에 주소 뜨면 뭐 404 에러뜸 
    #왜냐하면 /hello 라는 라우팅 에 만든것이기에 들아가서 /hello 통로로 들어가야뜸
  • /입력
from flask import Flask

app = Flask(__name__)

@app.route("/<username>")
def hello(username):
    return f'<h1>안녕 {username}</h1>'

if __name__ == "__main__":
    app.run(host="0.0.0.0", port = "8080")
  • /type 지정
# @app.rount("/meesage/<int:message_id>") # 타입 지정가능 기본형은 문자열

from flask import Flask

app = Flask(__name__)

def add_file(data):
    return data + 5

@app.route("/")
def hello():
    return '<h1>Hello World!</h1>'

@app.route("/message/<int:message_id>")  # message_id를 정수로 받음
def get_message(message_id):
    return f"message id: {message_id}"

@app.route("/first/<int:message_id>")  # message_id와 함수 매개변수 이름 일치
def get_first(message_id):
    data = add_file(message_id)  # message_id를 함수로 전달
    return f'<h1>{data}</h1>'

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)  # 포트는 정수로 지정

REST API 플라스크로 구현하기

데이터를 가져오기 위해서 http 프로토콜을 쓸때를 RestAPI 라 함
REST(REpresentational State Transfer)

  • 자원의 표헨ㅇ 의한 상태 전달
  • HTTP URL를 통해 자원을 명시하고, HTTP Method 를 통해 자원에 대한 CRUD Operation 적용
    - creat : POST(생성)
    - read : GET(조회)
    - update : 수정 (PUT)
    - delete : 삭제 (DELETE)
    REST API
  • REST 기반으로 서비스 API를 구현한 것
  • 마이크로 서비서, Open API 등에서 많이 사용됨
  • JSON 타입이 현재 제일 많이 쓰임
  • jsonify 사용해서 전달하기
from flask import Flask, jsonify
app = Flask(__name__)

@app.route('/json_test')
def hello_json():
    data = {'name' : '김대리', 'family' : 'Byun'}
    return jsonify(data)

@app.route('/server_info')
def server_json():
    data = {'server_name' : '0.0.0.0', 'server_port' : '8080'}
    return jsonify(data)

if __name__ =='__main__':
    app.run(host='0.0.0.0', port =8080)

📌 get 사용법

  • username = request.args.get('user_name') 코드면
  • get 을 쓰려면 주소값 제일 뒤에 http GET http://localhost:8080/login?user_name=dave 이런식으로 사용한다 ? 를붙여서 입력 그다음 파라미터는 & 앤드 를 넣는다

📌 플라스크로 정적 웹페이지 로드하기

  • temlplates 안에 html 파일을 넣음 반환값에 그 파일 이름을 씀

  • jsonify 딕셔너리형 데이터 집합을 json 형태로 포맷하여 전달

  • request /주소 값 뒤에 변수들을 받으려고 사용하는 것

  • method="get" 인 방식은 주소값 뒤에 파라미터 값이 입력되면 파리미터 변수값과 같이 가져옴

    • 해당 파라미터의 이름을 알고잇으면 플라스크 에서 그해당 값을 사용할 수 있다
  • 터미널 httpie 환경에서 실행된 플라스크에서 파리미터 값을 넣어줄 수있음 그러면 ?물음표를 쓰고 = 를하면 설정 가능 자동으로 역슬래쉬가 생성 될꺼임

  • ?user_name=dave 이런식으로 작성

  • 여러개 넣으려면 ?첫 파라미터=xx&두번째파라미터=xx&세번째파라미터 이런식으로 사용

📌 render_template('html파일명')

  • html파일은 flask 가 실행되는 하위 폴더인 templates 폴더 안에 위치해야함
  • 즉 파이썬에서 앱을 실행 시키고
@app.route('/html_test') # 라우팅 경로 설정
def hello_html():
    return redner_template('login.html')
    # 하위폴더에 template 안에 있는 longin.html 파일을 찾아서 실행시킨다라고 생각 찾아서 반환 시킨다 
    # 해당 을 런 시키고 주소창에 해당 라우팅 경로의 주소로 들어가면 template 폴더 안에 있는 login.html 파일을 실행시킨다 
    # 즉 html 을 라이브로 실행 시킨 것이 아니라 플라스크로 서버를 실행 시킨 것임
    
@app.route('/login')
def login(): # GET 방식은 뒤에 값이 파라미터 값으로 전달됨 그래서 그냥 주소만 입력하면 user_name 아 아무것도 안들어감
    username = request.args.get('user_name') # get방식 사용 하면 주소에 붙어서 나옴
    passwd = request.args.get('pw')
    email = request.args.get('email_address')
    print (username, passwd, email)
    
    if username == 'hak':
        return_data = {'auth': 'success'}
    else:
        return_data = {'auth': 'failed'}
    return jsonify(return_data) # 이렇게 보내면 프론트 앤드가 받음
  • 즉 hello_html라우팅 경로에 login.html 을 반환시키고 그래서 실행되면
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <form action="/login" method="get">
      <p>Enter Name:</p>
      <p><input type="text" name="user_name" /></p>
      <p><input type="text" name="pw" /></p>
      <p><input type="text" name="email_address" /></p>
      <p><input type="submit" value="submit" /></p>
    </form>
  </body>
</html>
  • 처음한것 뒤에 적은것을 그대로 변수로 넣어서 받기 바로 페이지에 띄우기

  • 두번째 한것

      1. html 폼을 생성해서 action 에 경로를 작성 / method get 요청을 보냄 (submit 을 누르면 가는거임)
      2. 예를들어 user_name 이라는 키로 서버에 전달됨
      3. 클라이언트가 요청한 것을 request.args.get('user_name')으로 읽어옴
    • 동작 순서

      1. /html_test 라우트로 접속
      2. 반환된 html의 형식으로 들어가짐 (login.html)
      3. html 코드안에서는 입력폼이 적혀져 있음
      4. action(여기서 작동하게 만들꺼다 라는것) 안에 경로로 입력한 것이 get 즉 받아서 넣는다
      5. 그후 어떻게 작동할지 저장해놓은 flask 경로 즉 app("/login")여기로 들어가면 어덯게 작동할지 작성해놓은 플라스크 구문으로 들어간다
      6. request.arges.get('username') 받은 것이 맞으면 어떤 것이 나오는지
      7. jsonify 한 파일로 전환된 코드로 나옴
    • 작성과정

      1. 우선 이코드를 사용할 경로를 지정 그리고 어떤 동작을 할건지 코드를작성
      2. 받을 입력을 받을 라우팅 경로를 지정 그리고 render_template 을 사용해 입력을 넣을 html 코드로 이동시킬 코드작성 (html 코드를 반드시 template 폴더만들어서 안에 넣기
      3. html 코드 작성 action 라우팅 경로에 동작에 적엇던 경로 작성 method get 을 사용해 전달할 변수들 작성 name=' '안에 넣어서 변수명일치시키기 중요
  • 세번째 지금 배우는것

    • jinja2 템플릿을 통하여 변수를 html로 전달시켜서 html 내에서 프로그래밍을 해서 화면에 띄워주는것
    • 작성과정
      1. flask 코드 작성 해서 template 내에 있는 html 파일에 render_temlpate 을 통해 전달
      2. html 코드 작성 그러면 화면 보여짐

📖 Jinja2 템플릿

  • 웹페이지에 필요한 부분을 변경할 필요가 있을 때 사용하는 간단한 문법
  • 웹페이지에서 파이썬 프로그래밍이 가능
  • 문법이므로 세세한 기능이 있지만, 처음 익힐 때는 핵심에 집중
  • 다음 두 가지 문법이 핵심
    • {{ 변수명 }}
    • {% 파이썬 소스코드 %}
  • 변수명이나 파이썬 소스코드를 조건이나 변수명을 html 코드로 반환되는 것
  • 일종의 프로그래밍 문법임
from flask import Flask, render_template
app = Flask(__name__)

@app.route('/hello/<user>')
def hello_name(user):
    return render_template('varable.html', name=user)

@app.route('/hello/<user>')
def hello_name(user):
    return render_template('varable.html', name=user,name2=user2,nae2...) # 여러개를 쓰려면 그냥 여러개를 쓰면됨 varable.html 코드에도 사용할 것으 여러개를 적어 놓으면 됨

if __name__=="__main__":
    app.run(host="0.0.0.0", port="8080")
  • 진자2 템플릿이란 경로상에 쓰면 그것을 데코레이터로 적혀있는 함수에서 것을 반환해 준다 위에서 varable.html 여기에 들어간다 name 이라는 변수에
  • 그리고서 varable.html 코드에서 사용하려면 {{name}} 이런식으로 안에서 사용 하면된다 변수명을 적거나 파이썬 소스코드를 활용해서 이런것을 만들 수 있따
  • 또한 여러개의 변수도 사용할 수 있다 그냥 뒤에 변수를 여러개 넣어주면된다 name=user,hak = 2, 이런식 별거 없음

jinja2 템플릿의 반복문

{% for %} 로선언하고 {% endfor %} 로 끝남
들여쓰기는 안해도 됨

from flask import Flask, render_template
app =Flask(__name__)

@app.route('/hello_loop')
def hello_name():
    value_list = ['list1','list2','list3']
    return render_template('loop.html', values=value_list)

<ul> #목차
    {% for value in values %}
    <li> value </li>
    {% endfor %}
</ul>

for i in range(len(values) -> 파이썬

{% for i in range(vlaues | length) %}-> html
<li>{{values[i]}} {{loop.index}}</li> 1 반복 할떄마다 횟수가 1번부터 나옴
{% endfor %}

조건문

{% if %} {% elif %} {% else %} {% endif %}

{% if data >= 30 %}
<h3>30보다 큽니다</h3>
{% endif %} # 꼭써야댐

{#   #} -> 진자2 템플릿에서의 주석처리

## 실제 프론트엔드(vue)와 flask 기반 RestAPI
> 백엔드는 REST API 를 제공해서 프론트엔드 쪽과 통신하면서 적합한 데이터를 제공해주는 역할을 함
> REST API 기반 기술은 HTTP 프로토콜을 사용해서 requests와 response를 주고받는 형식으로 이루어저 있음
> http 프로토콜에서 요청을 보낼떄 여려가지 method 를 보낼 수 있음
> 4가지 method get, post, put, delete


#### CDN 이란?
* CDN(Contents Delivery Network) 지리적으로 떨어져 있는 사용자에게 컨텐츠 제공자의 컨텐츠를 빠르게 제공할 수 있는 기술을 의미
* 사용자가 멀리 있는 서버로부터 컨텐츠를 받으면 오래 걸리기에 사용자와 가장 가까운 곳에 위치한 Cache Server 에 해당 컨텐츠를 저장해 사용하는 기술


### HTTP 요청 메서드(request method)
* 클라이언트가 서버에 http 요청시 요청 목적을 알리는 표시
* get, post, put, delete 가 있음
* 요청 메서드에 따라 요청 데이터를 전달하는 방식에 차이가 있음

## vue : 익히기 쉬운 기술
> 일종의 웹페이지에서 사용자 인터페이스 또는 웹페이지의 조건이 달라짐에 따라서 해당 웹페이지의 특정 부분만 바로 변경 할 수 있는 기술
> 해당 부분 선택 해당 부분만 update

#### 폴더 구성
* vue 폴더에 flask 폴더 구분
* vue 폴더에 vue_test.html 파일 생성
  - 
* 관리할 해당 부분 지정 id 로 지정 통상적으로 `<div id="app">` 이렇게 사용한다 
```html
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

    <title>Hello, world!</title>
  </head>
  <body>
    <div>     
    <h1>Hello, world!</h1>
    </div>
    <div id="app">
        <center>
        <button type="button" class="btn btn-primary">GET</button> 
        <button type="button" class="btn btn-secondary">POST</button>
        <button type="button" class="btn btn-success">PUT</button>
        <button type="button" class="btn btn-danger">DELETE</button>
        </center>
    </div>
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>

    <!-- Vue Start -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  </body>
</html>
  • 현재 버튼을 만든 상태인데 버튼을 누르는 이벤트가 발생하면 어떤 뷰에 있는 함수를 호출할 수 있게끔 만들 수 있음
  • v-on:click='axios_test' 를 button html 코드 class 뒤에 넣어준다
<script>
      const app = new Vue({
        el: "#app", // 이부분만 바꿔주면 됨 이름 에 맞게 id 에 적은
        methods: {
          axios_test() {
            axios("http://localhost:8082/test", {
              method: "get",
            })
              .then((response) => {
                console.log(response);
              })
              .catch((error) => {
                console.log(error);
              });
          },
        },
      });
</script>

안에 이렇게 놓아줌

CORS(Cross Origin Resource Sharing)

  • 웹에서 사용하는 HTTP request 는 기본적으로 다른 도메인의 데이터를 요청 할 수 있음 img src =" "
  • 하지만 스크립트로 둘러싸인 코드에서 실행되는 http request는 동인할 서버에만 요청할 수 있음
  • 정확하게는 프로토콜, 호스트명, 포트가 동일해야함
  • 이를 Same Origin Policy 라 함
  • 우리는 지금 플래스크를 사용하고 있으니까 플래스크에 Same Origin Policy 를 설정해줘야함
  • from flask_cors import CORS를 선언하고
  • app으로 설정한 플라스크에 CORS(app) 으로 선언해주면 에러를 안낸다.
  • return make_response(jsonify(success=True), 200), 이런식으로도 리턴할 수 있음
data = {'success': True}
jsonify(data)

동일하한 표현임

  • make_response 는 flask에 있는 함수 import 해야함 http status 코드를 넘겨주려면 사용하는것 100,200,300,400,500 이런것들

'GET', 'POST', 'PUT', 'DELETE'

put과 delete 는 get 방식과 유사하게 동작함

  • POST : 해당 데이터를 json 형식으로 가져 올 수 있음
    • data = request.get_json()
    • print(data['email'] 이런식으로 사용
  • GET, PUT, DELETE : 해당 데이터 가져와서 사용하는것
    • data = request.args.get('email')
# request 라는 함수를 import 하면 request.method == '' 어떤 메소드인지 확인할 수 있음
# from flask import request
@app.route("/test", methods=['GET', 'POST', 'PUT', 'DELETE']) # 메서드를 제한할 수 있음 설정을 안하면 GET방식만 지원받음
def test():
    if request.method == 'POST': # 해당 데이터를 json 형태로 가져와 질 수 있음
        print ('POST')
        data = request.get_json()
        print (data['email'])
    if request.method == 'GET':
        print ('GET')
        user = request.args.get('email')
        print (user)
    if request.method == 'PUT':
        print ('PUT')
        user = request.args.get('email')
        print (user)
    if request.method == 'DELETE':
        print ('DELETE')
        user = request.args.get('email')
        print (user)

    return jsonify(
        {'status': 'success'}
    )
    <div id="app">
      <br />
      <center>
        <button type="button" class="btn btn-primary" v-on:click="test_get">
          GET
        </button>
        <button type="button" class="btn btn-secondary" v-on:click="test_post">
          POST
        </button>
        <button type="button" class="btn btn-success" v-on:click="test_put">
          PUT
        </button>
        <button type="button" class="btn btn-danger" v-on:click="test_delete">
          DELETE
        </button>
      </center>
    </div>
          test_get: () => {
            axios("http://localhost:5000/test", {
              method: "get",
              params: {
                email: "test@test.com",
              }
            })
              .then((response) => {
                console.log(response.data['status']);
              })
              .catch((error) => {
                console.log(error);
              });
          },
          test_post: () => {
            axios("http://localhost:5000/test", {
              method: "post",
              data: {
                email: "test@test.com",
              }
            })
              .then((response) => {
                console.log(response.data["status"]);
              })
              .catch((error) => {
                console.log(error);
              });
          },
          test_put: () => {
            axios("http://localhost:5000/test", {
              method: "put",
              params: {
                email: "test@test.com",
              }
            })
              .then((response) => {
                console.log(response.data["status"]);
              })
              .catch((error) => {
                console.log(error);
              });
          },
          test_delete: () => {
            axios("http://localhost:5000/test", {
              method: "delete",
              params: {
                email: "test@test.com",
              }
            })
              .then((response) => {
                console.log(response.data["status"]);
              })
              .catch((error) => {
                console.log(error);
              });
          }
  • html 에서는 get과 post 만 지원
    • get은 상단에 나오고
    • post 는 바디에 출력되기에 보안에 더좋음
<form method="post" action="input.html">
    id: <input tpye="text" name="id"/>
    pw: <input type="texT" name="pw"/>
    <input type="submit"/>
</form>

에러 다루기

  • 없는 페이지를 요청 했을떄, 404
    • @app.errorhandler(404)
    • def page_not_found(error): return "<h3>404 Error 나옴!</h3>, 404
from flask import Flask
import requests

app = Flask(__name__)

@app.errorhandler(404) # 없는 페이지 요청시
def page_not_found(error):
    return "<h3>404 Error </h3>", 404

@app.route("/google")
def get_google():
    response = requests.get("http://www.google.co.kr")
    return response.text

if __name__ == "__main__" :
    app.run(host="0.0.0.0", port ="8080")
  • 로깅(logging) 다루기
    • 서버는 24시간 동작하므로 문제가 있을때, 문제가 있었는지, 파악하기 위해 로깅 기능을 사용함
    • 몇시 몇분에 에러가 발생 했는지 기록해두는 것
  • 파이썬은 logging 라이브러리가 있음
    • DEBUG > INFO > WARNING > ERROR > Critical (보통 eroor 이상만 저장함)
import logging
# 파일로 남기기 위해서는 filename='test.log' 파라미터, 어느로그 까지남길것인지 level로 설정 가능
logging.basicConfig(filename='test.log', level = logging.ERROR)
# 바로 하면 DEBUG 를 ERROR 로 바꾸면 실행안되고 주피터 노트북을껏다 키면 바뀜 

# 로그를 남길 부분에 다음과 같이 로그 레벨에 맞추어 출력해주면 해당 내용이 파일에 들어감
logging.debug("debug") # 제일윗단계라 전체 남겨짐
logging.info("info")
logging.warning("warning")
logging.error("error")
logging.critical("ciritical")

flask 와 logging

logging 라이브러리와 함꼐 flask logging 사용 가능
logging handler 를 주로 사용함

  • 주요 logging handler
    • FileHandler : 파일로 로그를 저장
    • RotatingFileHandler : 파일로 로그를 저장하되, 파일이 정해진 사이즈를 넘어가면, 새로운 파일을 생성
      • maxBytes = 하나의 파일사이즈, backupCount = 파일갯수
      • 전체 파일을 다 쓰면, 다시 처음부터 덮어 씀
    • NTEventLogHandler : 윈도우 시스템 로그를 남김
    • SysLogHandler : 유닉스 계열 시스템의 syslog 로 남김
from flask import Flask 
import requests

app = Flask(__name__)

# 2021.12.06 업데이트
# 최근에는 app.debug 값을 app.run 에서 설정하기 전에, 미리 설정해주어야, 하단부 if not app.debug 에 설정이 
# 적용되는 것을 확인하였습니다. 따라서, app.debug 값을 미리 설정해주는 코드를 추가하였습니다
# 즉, app.run 에서의 debug 옵션과, app.debug 값을 기반으로 한 logging 설정은 분리된 설정으로 이해하시면 좋을 것 같습니다
app.debug = False

if not app.debug: # 기본적으로 deubg =True 임 상용화에선 False 그래서 확인하려면
    import logging
    from logging.handlers import RotatingFileHandler # logging 핸들러 이름을 적어줌
    file_handler = RotatingFileHandler('dave_server.log', maxBytes=2000, backupCount=10) 
    file_handler.setLevel(logging.WARNING) # 어느 단계까지 로깅을 할지를 적어줌
    app.logger.addHandler(file_handler) # app.logger.addHandler() 에 등록시켜줘야 app.logger 로 사용 가능

@app.errorhandler(404)
def page_not_found(error):
    app.logger.error(error)
    return "<h1>404 Error</h1>", 404

if __name__ == "__main__":
    app.run(host="0.0.0.0", port="8080", dubug=True) # debug False 로하면 if not 저기로 들어가짐

다양한 데코레이터

  • before_request : HTTP 요청이 들어올 때마다 실행
    • before_request 인자를 전달할 수는 없음
  • after_request : HTTP 요청 처리가 끝나고 브라우저에 응답하기 전에 실행
    • response를 인자로 받아야 하고, response 를 리턴해야 함
from flask import Flask, request

app = Flask(__name__)

# 첫 번째 요청 여부를 추적하기 위한 전역 변수
initialized = False

# 첫 번째 요청 전에 실행될 함수
def before_first_request():
    print("flask 실행 후 첫 요청 때만 실행")

# 모든 요청 전에 실행될 함수
@app.before_request
def before_request(): # 여긴 아직 아무것도 동작하지 않은 상태기에 전달할 내용이 없기에 반환할 것이 없는 것임
    global initialized
    if not initialized: # 처음 실행된 후에 바뀌기에 다시는 실행되지 않음
        before_first_request()
        initialized = True
    print("HTTP 요청이 들어올 때마다 실행")

# 모든 요청 후에 실행될 함수
@app.after_request
def after_request(response): # 항상 reponse 를 받아야하고
    print("HTTP 요청 처리가 끝나고 브라우저에 응답하기 전에 실행")
    return response # 반환해줘야함 끝난후에 나오는 거니까 어떤 응답이 왔는지 전달해 줘야 되기에 

@app.route("/hello")
def hello():
    return "<h1>Hello Flask!</h1>"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)

0개의 댓글

관련 채용 정보